Assembly 为什么在64位程序中%esp和%ebp的寄存器值总是负值?
这是一个GNU汇编程序Assembly 为什么在64位程序中%esp和%ebp的寄存器值总是负值?,assembly,x86,64-bit,gnu-assembler,Assembly,X86,64 Bit,Gnu Assembler,这是一个GNU汇编程序 .code32 #must add this line, otherwise, this program can't be complied. .section .data .section .text .global _start _start: pushl $3 #push second argument pushl $2 #p
.code32 #must add this line, otherwise, this program can't be complied.
.section .data
.section .text
.global _start
_start:
pushl $3 #push second argument
pushl $2 #push first argument
call power #call the function
addl $8, %esp #move the stack pointer back
pushl %eax #save the first answer before calling the next function
pushl $2 #push second argument
pushl $5 #push first argument
call power #call the function
addl $8, %esp #move the stack pointer back
#The second answer is already
#in %eax. We saved the
#first answer onto the stack,
#so now we can just pop it
#out into %ebx
popl %ebx
addl %eax, %ebx #add them together
movl $1, %eax #exit (%ebx is returned)
int $0x80
.type power, @function
#first arg-> base number
#second arg-> the power to raise
power:
pushl %ebp #save old base pointer
movl %esp, %ebp #make stack pointer the base pointer
subl $4, %esp #get room for our local storage
movl 8(%ebp), %ebx
movl 12(%ebp), %ecx
movl %ebx, -4(%ebp)
power_loop_start:
cmpl $1, %ecx
je end_power
movl -4(%ebp), %eax
imull %ebx, %eax
movl %eax, -4(%ebp)
decl %ecx
jmp power_loop_start
end_power:
movl -4(%ebp), %eax
movl %ebp, %esp
popl %ebp
ret
当添加.code32
指令时,可以遵守该指令
$ as -g hello.s -o hello.o
$ ld hello.o -o hello
但是,在运行时,它总是显示“段故障”
我发现当使用GDB进入power
时,%esp和%ebp的寄存器总是负值
Breakpoint 1, _start () at hello.s:9
9 pushl $3
(gdb) n
_start () at hello.s:10
10 pushl $2
(gdb)
_start () at hello.s:11
11 call power
(gdb) s
power () at hello.s:35
35 pushl %ebp
(gdb) n
36 movl %esp, %ebp
(gdb)
37 subl $4, %esp
(gdb) n
power () at hello.s:45
45 movl 8(%ebp), %ebx
(gdb) print $ebp
$1 = -8144
(gdb) print $esp
$2 = -8148
(gdb)
我怎样才能解决这个问题。我的操作系统是Ubuntu
Linux locomotive-VirtualBox 5.4.0-52-generic #57~18.04.1-Ubuntu SMP Thu Oct 15 14:04:49 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
因为Linux将用户空间堆栈指针放在虚拟地址空间的顶部附近,虚拟地址空间靠近4GiB区域的顶部,32位进程可以在64位内核下使用4GiB区域。通常,您希望以十六进制打印指针,如
p/x$ebp
。这不是您需要解决的问题(除了您选择将它们打印为带符号的十进制数)。哦,等等,.code32
不会生成32位进程,它只允许您将32位机器代码放入一个可执行文件中,该可执行文件仍会将其解码为64位;幸运的是,它没有中断(任何涉及符号的寻址模式,或寄存器的inc/dec,或任何假定push
会将ESP移动4而不是8的寻址模式),当然push
,pop
,或call
会在sub$4,%ESP
将RSP截断为32位ESP后发生故障。