當我寫了如下匯編時
; nasm -f elf64 -g -F dwarf charsin.asm
; gcc charsin.o -no-pie -o charsin
; ld -o eatclib eatclib.o
; gdb eatclib[SECTION .data]SPrompt db 'Enter string data, followed by Enter: ',0IPrompt db 'Enter an integer value, followed by Enter: ',10,0IFormat db "%d",0SShow db 'The string you entered was: %s',0IShow db 'The Integer value you entered was: %5d',10,0[SECTION .bss]IntVal resd 1InString resb 128 [SECTION .text]extern stdinextern fgetsextern printfextern scanfglobal mainmain:push rbpmov rbp,rsppush rbxpush rsipush rdi;push SPromptmov rdi,SPrompt ; 傳遞參數mov rax,0call printf;add rsp,8; rdi,rsi,rdx,rcx分別保存第1,2,3,4個參數;push qword [stdin];push 72;push InStringmov rdi,InStringmov rsi,72mov rdx,[stdin]mov rax,0call fgets;add rsp,24;push InString;push SShowmov rdi,SShowmov rsi,InString;在匯編代碼中,若是調用變長參數的函數,需要使用al這個寄存器記錄使用到的向量寄存器數量。;這段代碼中eax中存放的不是系統調用號,存放的是向量寄存器使用到的數量0,因為printf使用的是變長參數。mov rax,0call printf;add rsp,16mov rax,0push IPromptmov rdi,IPrompt ; 傳遞參數call printfadd rsp,8;push IntVal;push IFormatmov rdi,IFormat mov rsi,IntVal ; 保留數字的內存地址xor rax,raxcall scanf;add rsp,16;mov rax, 0 ;sys_read 系統調用號;mov rdi, 0 ; 文件描述符 標準輸入;mov rsi,IntVal ; 保留數字的內存地址;mov rdx, 4;syscallxor rsi,rsimov rax,0mov rdi,IShow ; 傳遞格式參數mov esi,[IntVal]call printf;add rsp,16pop rdipop rsipop rbxmov rsp,rbppop rbpret
編譯后,系統會如下段錯誤(Segmentation fault (core dumped)).
在函數的開始/結束處使用 sub rsp, 8/add rsp, 8 將堆棧重新對齊到 16函數執行調用之前的字節。
; nasm -f elf64 -g -F dwarf charsin.asm
; gcc charsin.o -no-pie -o charsin
; ld -o eatclib eatclib.o
; gdb eatclib[SECTION .data]SPrompt db 'Enter string data, followed by Enter: ',0IPrompt db 'Enter an integer value, followed by Enter: ',10,0IFormat db "%d",0SShow db 'The string you entered was: %s',0IShow db 'The Integer value you entered was: %5d',10,0[SECTION .bss]IntVal resd 1InString resb 128 [SECTION .text]extern stdinextern fgetsextern printfextern scanfglobal mainmain:push rbpmov rbp,rsppush rbxpush rsipush rdi;在函數的開始/結束處使用 sub rsp, 8/add rsp, 8 將堆棧重新對齊到 16函數執行調用之前的字節。sub rsp, 8;push SPromptmov rdi,SPrompt ; 傳遞參數mov rax,0call printf;add rsp,8; rdi,rsi,rdx,rcx分別保存第1,2,3,4個參數;push qword [stdin];push 72;push InStringmov rdi,InStringmov rsi,72mov rdx,[stdin]mov rax,0call fgets;add rsp,24;push InString;push SShowmov rdi,SShowmov rsi,InString;在匯編代碼中,若是調用變長參數的函數,需要使用al這個寄存器記錄使用到的向量寄存器數量。;這段代碼中eax中存放的不是系統調用號,存放的是向量寄存器使用到的數量0,因為printf使用的是變長參數。mov rax,0call printf;add rsp,16mov rax,0push IPromptmov rdi,IPrompt ; 傳遞參數call printfadd rsp,8;push IntVal;push IFormatmov rdi,IFormat mov rsi,IntVal ; 保留數字的內存地址xor rax,raxcall scanf;add rsp,16;mov rax, 0 ;sys_read 系統調用號;mov rdi, 0 ; 文件描述符 標準輸入;mov rsi,IntVal ; 保留數字的內存地址;mov rdx, 4;syscallxor rsi,rsimov rax,0mov rdi,IShow ; 傳遞格式參數mov esi,[IntVal]call printf;add rsp,16;在函數的開始/結束處使用 sub rsp, 8/add rsp, 8 將堆棧重新對齊到 16函數執行調用之前的字節。add rsp, 8pop rdipop rsipop rbxmov rsp,rbppop rbpret
編譯后,程序運行正常。
參考段錯誤
StackOverflow