【发布时间】:2016-11-25 02:15:58
【问题描述】:
以下代码使用 rsi 寄存器作为循环计数器打印 hello world 10 次。
section .data
hello: db 'Hello world!',10
helloLen: equ $-hello
section .text
global _start
_start:
mov rsi, 0 ;<--- use r8 here
do_loop:
inc rsi ;<--- use r8 here
;print hello world
mov eax,4
mov ebx,1
mov ecx,hello
mov edx,helloLen
int 80h
cmp rsi, 10 ;<--- use r8 here
jnz do_loop
;system exit
mov eax,1 ; The system call for exit (sys_exit)
mov ebx,0 ; Exit with return code of 0 (no error)
int 80h;
如果我尝试使用 r8 寄存器而不是 rsi 作为循环计数器,则会导致无限循环。这里的 r8 寄存器只是一个例子。它也发生在寄存器 r9、r10 上。
谁能解释一下,因为我认为这些都是通用寄存器,应该允许你使用它们?
【问题讨论】:
-
您在 64 位模式下使用 32 位系统调用。坏主意。
-
有趣。当从 64 位代码调用时,也许 Linux 的
int 0x8032 位 ABI 会破坏高位寄存器?在 Linux 中,syscall破坏了 rcx 和 r11,但保留了其他所有内容(当然,返回值的 rax 除外)。通常人们在尝试传递不适合 32 位的指针时会遇到int 0x80ABI 的问题。 (导致-EFAULT) -
尝试使用
layout reg在 gdb 中单步执行以突出显示更改的 regs。 (见底部x86 tag wiki -
不仅高位,而且 64 位额外寄存器作为一个整体没有被 32 位系统调用保存,原因很明显。几乎没有“奇怪”。
-
好吧,情况似乎和我想象的不一样,compatibility int 80 handler 实际上将
r8到r11的寄存器显式归零,并保留了其他寄存器的全部 64 位(rax除外这当然是返回值)。
标签: linux assembly x86-64 nasm system-calls