在64位Linux上使用中断0x80 [英] Using interrupt 0x80 on 64-bit Linux

查看:176
本文介绍了在64位Linux上使用中断0x80的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的64位汇编程序,旨在打印'O'和'K',后跟换行符. 但是,永远不会打印"K".程序的目标之一是将rax寄存器低位的值打印为ASCII字母.该程序专门用于64位Linux,是出于教学目的而编写的,因此无需使用C样式的系统调用.

I have a simple 64-bit assembly program which is intended to print an 'O' and 'K' followed by a newline. However, the 'K' is never printed. One of the goals of the programs is to print the value in the lower bits of the rax register as ASCII letter. The program is specifically for 64-bit Linux, written for educational purposes, so there is no need to use C-style system calls.

我怀疑问题出在mov QWORD [rsp], rax还是mov rcx, rsp.

当前,该程序仅输出'O',后跟换行符.

Currently, the program only outputs 'O' followed by a newline.

如何更改程序以使其使用rax中的值,然后打印"K",以使完整的输出为"OK",然后换行?

How can one change the program to make it use the value in rax and then print a 'K' so that the complete output is 'OK' followed by a newline?

bits 64

section .data

o:  db "O"      ; 'O'
nl: dq 10       ; newline

section .text

;--- function main ---
global main         ; make label available to the linker
global _start       ; make label available to the linker
_start:             ; starting point of the program
main:               ; name of the function

;--- call interrupt 0x80 ---
mov rax, 4          ; function call: 4
mov rbx, 1          ; parameter #1 is 1
mov rcx, o          ; parameter #2 is &o
mov rdx, 1          ; parameter #3 is length of string
int 0x80            ; perform the call

;--- rax = 'K' ---
mov rax, 75         ; rax = 75

;--- call interrupt 0x80 ---
sub rsp, 8          ; make some space for storing rax on the stack
mov QWORD [rsp], rax        ; move rax to a memory location on the stack
mov rax, 4          ; function call: 4
mov rbx, 1          ; parameter #1 is 1
mov rcx, rsp            ; parameter #2 is rsp
mov rdx, 1          ; parameter #3 is length of string
int 0x80            ; perform the call
add rsp, 8          ; move the stack pointer back

;--- call interrupt 0x80 ---
mov rax, 4          ; function call: 4
mov rbx, 1          ; parameter #1 is 1
mov rcx, nl         ; parameter #2 is nl
mov rdx, 1          ; parameter #3 is length of string
int 0x80            ; perform the call

;--- exit program ---
mov rax, 1          ; function call: 1
xor rbx, rbx            ; return code 0
int 0x80            ; exit program

推荐答案

很明显,您编写了64位程序,并使用了"int 0x80"指令. "int 0x80"只能在32位程序中正常工作.

Obviously you write a 64-bit program and you use the "int 0x80" instruction. "int 0x80" however only works correctly in 32-bit programs.

堆栈的地址在32位程序无法访问的范围内.因此,很有可能"int 0x80"样式的系统调用不允许访问此内存区域.

The address of the stack is in a range that cannot be accessed by 32-bit programs. Therefore it is quite probable that "int 0x80"-style system calls do not allow accessing this memory area.

要解决此问题,有两种可能性:

To solve this problem there are two possibilities:

  • 作为32位应用程序进行编译(使用EAX之类的32位寄存器而不是RAX之类的64位寄存器).在不使用任何共享库的情况下进行链接时,32位程序将在64位Linux上完美运行.
  • 使用"syscall"样式的系统调用而不是"int 0x80"样式的系统调用.这些功能与"int 0x80"样式的功能有很大不同!

32位代码:

mov eax,4    ; In "int 0x80" style 4 means: write
mov ebx,1    ; ... and the first arg. is stored in ebx
mov ecx,esp  ; ... and the second arg. is stored in ecx
mov edx,1    ; ... and the third arg. is stored in edx
int 0x80

64位代码:

mov rax,1    ; In "syscall" style 1 means: write
mov rdi,1    ; ... and the first arg. is stored in rdi (not rbx)
mov rsi,rsp  ; ... and the second arg. is stored in rsi (not rcx)
mov rdx,1    ; ... and the third arg. is stored in rdx
syscall

---编辑---

背景信息:

"int 0x80"适用于32位程序.从64位程序调用时,其行为与从32位程序中调用(使用32位调用约定)时的行为相同.

"int 0x80" is intended for 32-bit programs. When called from a 64-bit program it behaves the same way it would behave like if it has been called from a 32-bit program (using the 32-bit calling convention).

这也意味着"int 0x80"的参数将在 32位寄存器中传递,而64位寄存器的高32位将被忽略.

This also means that the parameters for "int 0x80" will be passed in 32-bit registers and the upper 32 bits of the 64-bit registers are ignored.

(我刚刚在64位Ubuntu 16.10上进行了测试.)

(I just tested that on Ubuntu 16.10, 64 bit.)

但是,这意味着您在使用"int 0x80"时只能访问2 ^ 32以下(甚至低于2 ^ 31)的内存,因为您不能在32位寄存器中传递2 ^ 32以上的地址.

This however means that you can only access memory below 2^32 (or even below 2^31) when using "int 0x80" because you cannot pass an address above 2^32 in a 32-bit register.

如果要写入的数据位于2 ^ 31以下的地址,则可以使用"int 0x80"来写入数据.如果它位于2 ^ 32以上,则不能.堆栈(RSP)很可能位于2 ^ 32以上,因此您不能使用"int 0x80"在堆栈上写入数据.

If the data to be written is located at an address below 2^31 you may use "int 0x80" to write the data. If it is located above 2^32 you can't. The stack (RSP) is very likely located above 2^32 so you cannot write data on the stack using "int 0x80".

因为您的程序很可能会使用2 ^ 32以上的内存,我写道:"int 0x80不适用于64位程序."

Because it is very likely that your program will use memory above 2^32 I have written: "int 0x80 does not work with 64-bit programs."

这篇关于在64位Linux上使用中断0x80的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆