linux - int 0x80 是否覆盖寄存器值?

标签 linux assembly gdb 64-bit nasm

<分区>

我写了一个程序,它应该表现得像一个 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

最佳答案

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

具体来说,来自 System V 应用程序二进制接口(interface) x86-64™ 架构处理器补充 [ PDF link ], 附录 A,x86-64 Linux 内核约定:

The interface between the C library and the Linux kernel is the same as for the user-level applications...

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

关于linux - int 0x80 是否覆盖寄存器值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17870031/

相关文章:

c - 缓冲区溢出视频中的 jmp *%esp

gcc - 反汇编简单二进制文件时这些额外的指令是什么?

c - 为什么 GDB 无法识别我的 C 程序的语言?

linux - Node.js 的性能问题 (Mac OSX) - 进程

linux - 我在 unix 中 at 作业的输出中不断收到 'while syntax' 错误,我不知道为什么

assembly - 自修改代码算法

c++ - 这是GDB本身的段错误吗?

debugging - 是否可以在不停止调试程序的情况下向 gdb 发出命令?

php - 为什么在我的系统中默认的 PHP 时区是 "Europe/Moscow"?

linux - 调试符号是否加载到 Linux 的内存中?