【问题标题】:Does int 0x80 overwrite register values? [duplicate]int 0x80 会覆盖寄存器值吗? [复制]
【发布时间】:2013-07-26 01:19:26
【问题描述】:

我写了一个程序,它的行为应该类似于 for while 循环,打印一个文本字符串一定次数。

代码如下:

global _start


    section .data
    
    msg db "Hello World!",10    ; define the message
    msgl equ $ - msg            ; define message length
                                ; use minimal size of storage space

    imax dd 0x00001000          ; defines imax to be big!

    section .text
_start:


    mov r8, 0x10          ; <s> put imax in r8d, this will be our 'i' </s>
                          ; just attempt 10 iterations
_loop_entry:                    ; loop entry point
    mov eax, 4                  ; setup the message to print
    mov ebx, 1                  ; write, stdout, message, length
    mov ecx, msg
    mov edx, msgl
    int 0x80                    ; print message
                                ; this is valid because registers do not change
    dec r8                      ; decrease i and jump on not zero
    cmp r8,1                    ; compare values to jump
    jnz _loop_entry


    mov rax, 1                  ; exit with zero
    mov rbx, 0
    int 0x80

我遇到的问题是程序运行到无限循环中。我在 gdb 中运行它,原因是:

调用int 0x80 来打印消息,这可以正常工作,但是在中断完成后,r8 的内容被设置为零,而不是它应该是的值。 r8 是计数器所在的位置,计数(向下)打印字符串的次数。

int 0x80 是否修改寄存器值?我注意到 rax、rbx、rcx、rdx 没有受到同样的影响。

测试结果

回答:是的!它确实修改了 r8。

我在我的程序中改变了两件事。首先我现在cmp r8, 0,来获取Hello World!正确的次数,以及

我已经添加了

mov [i], r8                 ; put away i

_loop_entry:之后

我也添加了

mov r8, [i]                 ; get i back

在第一个int 0x80之后。

这是我现在正在运行的程序。更多关于 C++ 性能的信息。

;
;   main.asm
; 
; 
;   To be used with main.asm, as a test to see if optimized c++
;   code can be beaten by me, writing a for / while loop myself. 
; 
; 


;  Absolute minimum code to be competative with asm.


global _start


    section .data
    
    msg db "Hello World!",10    ; define the message
    msgl equ $ - msg            ; define message length
                                ; use minimal size of storage space

    imax dd 0x00001000          ; defines imax to be big!
    i dd 0x0                    ; defines i
    
    section .text
_start:


    mov r8, 0x10          ; put imax in r8d, this will be our 'i'
_loop_entry:                    ; loop entry point
    mov [i], r8                 ; put away i
    mov eax, 4                  ; setup the message to print
    mov ebx, 1                  ; write, stdout, message, length
    mov ecx, msg
    mov edx, msgl
    int 0x80                    ; print message
                                ; this is valid because registers do not change
    mov r8, [i]                 ; get i back
    dec r8                      ; decrease i and jump on not zero
    cmp r8,0                    ; compare values to jump
    jnz _loop_entry


    mov rax, 1                  ; exit with zero
    mov rbx, 0
    int 0x80

【问题讨论】:

  • 在 64 位代码中使用时,32 位 int 0x80 ABI 会将 r8-r11 归零并保留其他所有内容。

标签: linux assembly gdb 64-bit nasm


【解决方案1】:

int 0x80 只会导致软件中断。在您的情况下,它被用于进行系统调用。是否有任何寄存器受到影响将取决于您正在调用的特定系统调用以及您平台的系统调用调用约定。有关详细信息,请阅读您的文档。

具体来说,来自System V Application Binary Interface x86-64™ Architecture Processor Supplement [PDF link],附录 A,x86-64 Linux 内核约定

C 库和 Linux 内核之间的接口与用户级应用程序的接口相同...

对于用户级应用程序,r8 是一个临时寄存器,这意味着它是调用者保存的。如果您希望通过系统调用保留它,您需要自己做。

【讨论】:

  • 好的,作为测试,我将 r8 保存并恢复到内存中 int 0x80 的任一侧。我会更新你
  • ABI 文档没有定义从 64 位模式使用的 32 位 int 0x80 ABI 如何处理寄存器 r8-r15 或 RAX 的高半部分等等。您的论点是虚假的,因为 r8 由 64 位 syscall 保留调用,这与函数调用不同。它相似,但有显着差异。无论如何,r8 在 64 位代码中被 int 0x80 归零。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-22
  • 1970-01-01
  • 2014-10-16
  • 1970-01-01
相关资源
最近更新 更多