nasm 使用 arg 时出现分段错误
nasm segmentation fault while using arg
extern puts
global main
section .text
main:
mov rax, rdi
label:
test rax, rax
je exit
push rsi
mov rdi, [rsi]
call puts
pop rsi
dec rax
add rsi, 8
jmp label
exit:
pop rsi
ret
我写了 nasm 那样的代码。但是最后发生分段错误。我不明白为什么会出现段错误。
rax
不能保证在函数调用中保留,因为它用于 return 函数的整数结果(在 puts
[ 的情况下) =19=]) 您需要在调用 puts
之前保存 rax
的值,就像您对 rsi
所做的那样,然后再恢复它。
显然您想在 64 位 Linux 的 GCC 环境中获取命令行参数,根据 Linux 调用约定之后的 GCC 调用约定传递它们" System V AMD64 ABI".
让我们把程序逻辑翻译成C:
#include <stdio.h>
int main ( int argc, char** argv )
{
if (argc != 0)
{
do
{
puts (*argv);
argc--;
argv++;
} while (argc);
}
return;
}
asm 程序没有 return 退出代码。当函数 returns 时,退出代码应该在 RAX
中。顺便说一句:argc
总是 >0,因为 argv
的第一个字符串包含程序名称。
main
函数既是"caller"(调用puts
)又是"callee"(return调用GCC环境)。作为调用者,它必须在调用 puts
之前保留 RAX
和 RSI
并在需要时恢复它们。不使用被调用者保存的寄存器。不要忘记将堆栈对齐 16.
这个有效:
extern puts
global main
section .text
main: ; RDI: argc, RSI: argv, stack is unaligned by 8
mov rax, rdi
label:
test rax, rax
je exit
push rbx ; Push 8 bytes to align the stack before the call
push rax ; Save it (caller-saved)
push rsi ; Save it (caller-saved)
mov rdi, [rsi] ; Argument for puts
call puts
pop rsi ; Restore it
pop rax ; Restore it
pop rbx ; "Unalign" the stack
dec rax
add rsi, 8
jmp label
exit:
; pop rsi ; Once too much
xor eax, eax ; RAX = 0 (return 0)
ret ; RAX: return value
extern puts
global main
section .text
main:
mov rax, rdi
label:
test rax, rax
je exit
push rsi
mov rdi, [rsi]
call puts
pop rsi
dec rax
add rsi, 8
jmp label
exit:
pop rsi
ret
我写了 nasm 那样的代码。但是最后发生分段错误。我不明白为什么会出现段错误。
rax
不能保证在函数调用中保留,因为它用于 return 函数的整数结果(在 puts
[ 的情况下) =19=]) 您需要在调用 puts
之前保存 rax
的值,就像您对 rsi
所做的那样,然后再恢复它。
显然您想在 64 位 Linux 的 GCC 环境中获取命令行参数,根据 Linux 调用约定之后的 GCC 调用约定传递它们" System V AMD64 ABI".
让我们把程序逻辑翻译成C:
#include <stdio.h>
int main ( int argc, char** argv )
{
if (argc != 0)
{
do
{
puts (*argv);
argc--;
argv++;
} while (argc);
}
return;
}
asm 程序没有 return 退出代码。当函数 returns 时,退出代码应该在 RAX
中。顺便说一句:argc
总是 >0,因为 argv
的第一个字符串包含程序名称。
main
函数既是"caller"(调用puts
)又是"callee"(return调用GCC环境)。作为调用者,它必须在调用 puts
之前保留 RAX
和 RSI
并在需要时恢复它们。不使用被调用者保存的寄存器。不要忘记将堆栈对齐 16.
这个有效:
extern puts
global main
section .text
main: ; RDI: argc, RSI: argv, stack is unaligned by 8
mov rax, rdi
label:
test rax, rax
je exit
push rbx ; Push 8 bytes to align the stack before the call
push rax ; Save it (caller-saved)
push rsi ; Save it (caller-saved)
mov rdi, [rsi] ; Argument for puts
call puts
pop rsi ; Restore it
pop rax ; Restore it
pop rbx ; "Unalign" the stack
dec rax
add rsi, 8
jmp label
exit:
; pop rsi ; Once too much
xor eax, eax ; RAX = 0 (return 0)
ret ; RAX: return value