movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
我使用以下 asm 代码打印EBX寄存器中的内容。当我使用
movl $1,%eax
int 0x80
echo $?
我得到了正确的答案,但在第一种情况下出现了分段错误。我正在使用 GNU 汇编器和 AT&T 语法。我该如何解决这个问题?
movl %ebx, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
我使用以下 asm 代码打印EBX寄存器中的内容。当我使用
movl $1,%eax
int 0x80
echo $?
我得到了正确的答案,但在第一种情况下出现了分段错误。我正在使用 GNU 汇编器和 AT&T 语法。我该如何解决这个问题?
从代码来看,您可能处于 64 位模式(请确认),在这种情况下,指针的大小为 64 位。在 Linux 上依赖于位置的可执行文件movl $.LC1, %edi
是安全的,并且编译器使用什么,但是为了使您的代码与位置无关并且能够处理在低 32 位之外的符号地址,您可以使用leaq .LC1(%rip), %rdi
.
此外,请确保:
rbx
你在你的功能中保留价值此代码适用于 64 位:
.globl main
main:
push %rbx
movl $42, %ebx
movl %ebx, %esi
leaq .LC1(%rip), %rdi
movl $0, %eax
call printf
xor %eax, %eax
pop %rbx
ret
.data
.LC1: .string "%d\n"
编辑:正如 Jester 所指出的,此答案仅适用于 x86(32 位)asm,而提供的示例更可能适用于 x86-64。
那是因为 printf 有可变数量的参数。printf 调用不会为您恢复堆栈,您需要自己进行。
在您的示例中,您需要编写(32 位汇编):
push %ebx
push $.LC1
call printf
add $8, %esp // 8 : 2 argument of 4 bytes