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

参见英文答案 > What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?                                    1个
我编写了一个程序,它应该像for循环一样,打印一串文本一定次数.

这是代码:

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 Application Binary 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中混合汇编和C的编程


下一篇:linux – 如何在我的64位机器上使用gcc编译32位.o文件?