当前位置: 首页 > 面试题库 >

x86 Assembly:在Linux上进行系统调用之前,应该保存所有寄存器吗?

袁鸿雪
2023-03-14
问题内容

我有下面的代码打开一个文件,将其读入缓冲区,然后关闭该文件。

关闭文件系统调用要求文件描述符号在ebx寄存器中。ebx寄存器在进行读取系统调用之前获取文件描述符号。我的问题是,在进行读取系统调用之前,我应该将ebx寄存器保存在堆栈中还是某处(int
80h是否可以丢弃ebx寄存器?)。然后恢复ebx寄存器以关闭系统调用?还是我下面的代码安全无虞?

我已经运行了下面的代码并且可以正常工作,我只是不确定是否通常被认为是良好的汇编习惯,因为在int 80h读取调用之前我没有保存ebx寄存器。

;; open up the input file 
mov eax,5        ; open file system call number
mov ebx,[esp+8]  ; null terminated string file name, first command line parameter
mov ecx,0o       ; access type: O_RDONLY
int 80h          ; file handle or negative error number put in eax
test eax,eax
js Error         ; test sign flag (SF) for negative number which signals error

;; read in the full input file
mov ebx,eax            ; assign input file descripter
mov eax,3              ; read system call number
mov ecx,InputBuff      ; buffer to read into
mov edx,INPUT_BUFF_LEN ; total bytes to read
int 80h
test eax,eax
js Error               ; if eax is negative then error
jz Error               ; if no bytes were read then error
add eax,InputBuff      ; add size of input to the begining of InputBuff location
mov [InputEnd],eax     ; assign address of end of input

;; close the input file
;; file descripter is already in ebx
mov eax,6       ; close file system call number
int 80h

问题答案:

int 80h调用本身不会破坏任何东西,除了把返回值eax。因此,您拥有的代码片段很好。(但是,如果您的代码片段是一个更大的例程的一部分,而该例程预期会被通常的Linux
x86 ABI之后的其他代码调用,则您需要ebx在进入例程时保留,可能还有其他寄存器,并在退出时进行恢复。 )

内核中的相关代码可以在中找到arch/x86/kernel/entry_32.S。由于宏的广泛使用和各种详细信息(支持syscall跟踪,DWARF调试注释等),因此很难遵循;但是:int 80h处理程序是system_call(我链接到的版本的493行);寄存器通过SAVE_ALL宏保存(第497行);并RESTORE_REGS在返回之前再次通过(第534行)将其恢复。



 类似资料:
  • 为系统程序员设计的寄存器可以分为以下几类: EFLAGS (标志寄存器) Memory-Management Registers (内存管理寄存器) Control Registers (控制寄存器) Debug Registers (调试寄存器) Test Registers (测试寄存器) 4.1.1 系统标志 (System Flags) 系统标志寄存器EFLAGS 控制着 I/O、可屏蔽中

  • 问题:执行相应行后,用保存在相应寄存器中的值填充间隙。以十六进制和32位输入所有值。 我的想法是:我是大会新手。我知道EAX、EBX、ECX、EDX、ESI、EDI、ESP或EBP等值适用于任何32位寄存器。或AX、BX、CX或DX等值适用于任何16位寄存器。我读过xor eax,eax-将eax的内容设置为零。这意味着第一个间隙是0x00000000,对吗?第二个gap将0x12345678复制

  • 我相信我了解linux x86-64 ABI如何使用寄存器和堆栈将参数传递给函数(参见前面的ABI讨论)。我感到困惑的是,在函数调用中是否/哪些寄存器应该保留。也就是说,哪些寄存器被保证不被破坏?

  • 问题内容: 我想使用gprof来分析守护程序。我的守护程序使用第3方库,通过该库注册一些回调,然后调用一个永不返回的函数。我需要调用(SIGTERM或SIGKILL)终止守护程序。不幸的是,gprof的手册页显示以下内容: 被分析的程序必须调用“ exit”(2)或正常返回,以将分析信息保存在gmon.out文件中。 有没有办法为使用SIGTERM或SIGKILL杀死的进程保存概要分析信息? 问题

  • 在wikipedia x86调用约定中,它说对于Microsoft x64调用约定: 寄存器RBX、RBP、RDI、RSI、RSP、R12、R13、R14和R15被视为非易失性(被叫方保存)。 但对于System V AMD64 ABI: 如果被调用方希望使用寄存器RBX、RBP和R12-R15,则必须在将控制权返回给调用方之前恢复它们的原始值。 我的问题是,在不同的平台上调用约定是不是不同的?(

  • 问题内容: 如何查看Java程序正在执行的系统?有没有可以在Linux上执行此操作的工具? 问题答案: 使用strace: