linux x86_64命令,关于linux:NASM x86_64在编写命令行参数时遇到问题,在rax中返回-14...

我正在使用elf64编译并尝试获取参数并将其写入控制台。

我将函数称为./test wooop

在单步执行gdb之后似乎没有问题,一切都设置好了:

rax:0x4

rbx:0x1

rcx:指向字符串,x / 6cb $ rcx给出'w''o''o''o''p'0x0

rdx:0x5

在int 80h之后,rax包含-14并且没有任何内容打印到控制台。

如果我在.data中定义一个字符串,它就可以了。 gdb以相同的方式显示$ rcx的值。

有任何想法吗? 这是我的完整来源

%define LF      0Ah

%define stdout      1

%define sys_exit    1

%define sys_write   4

global _start

section .data

usagemsg: db"test {string}",LF,0

testmsg: db"wooop",0

section .text

_start:

pop rcx     ;this is argc

cmp rcx, 2      ;one argument

jne usage

pop rcx

pop rcx               ; argument now in rcx

test    rcx,rcx

jz usage

;mov rcx, testmsg    ;

call print

jmp exit

usage:

mov rcx, usagemsg

call print

jmp exit

calclen:

push rdi

mov rdi, rcx

push rcx

xor rcx,rcx

not rcx

xor al,al

cld

repne scasb

not rcx

lea rdx, [rcx-1]

pop rcx

pop rdi

ret

print:

push rax

push rbx

push rdx

call calclen

mov rax, sys_write

mov rbx, stdout

int 80h

pop rdx

pop rbx

pop rax

ret

exit:

mov rax, sys_exit

mov rbx, 0

int 80h

谢谢

编辑:改变我如何使我的系统调用如下,它工作正常。 感谢你的帮助!

sys_write现在是1

sys_exit现在是60

stdout现在进入rdi,而不是rbx

要写的字符串现在在rsi中设置,而不是rcx

int 80h被syscall取代

我还在运行32位硬件,所以这是一个疯狂的猜测!您可能知道,64位系统调用号完全不同,使用"syscall"而不是int 80h。但是仍然可以使用int 80h和32位系统调用号,64位寄存器被截断为32位。您的测试表明这适用于.data中的地址,但是使用"堆栈地址"时,它返回-14(-EFAULT - 错误地址)。我唯一能想到的是,如果它在堆栈上,将rcx截断为ecx会导致"坏地址"。我不知道堆栈在64位代码中的位置。这有意义吗?

我尝试使用"正确的"64位系统调用号码和寄存器以及"系统调用",看看是否有帮助。

最好,

坦率

+1。 非常好的答案! 我甚至都不会想到这么明显的事情。

+1。 谢谢,这就是问题所在。 更改我的系统调用号码和我使用的寄存器后,它工作正常。

如你所说,你正在使用ELF64作为编译的目标。不幸的是,这是你的第一个错误。使用Linux上的"旧"系统调用接口,例如只有在运行32位任务时才可以使用int 80h。显然,您可以简单地将源组装为ELF32,但如果以64位模式运行任务,即额外的寄存器和64位操作,您将失去所有优势。

为了在64位任务中进行系统调用,必须使用"新"系统调用接口。系统调用本身是使用syscall指令完成的。内核破坏寄存器rcx和r11。系统的编号在寄存器rax中指定,而调用的参数在rdi,rsi,rdx,r10,r8和r9中传递。请记住,系统调用的数量与32位模式下的数量不同。您可以在unistd_64.h中找到它们,通常位于/usr/include/asm或您的发行版存储它的位置。

谢谢您的帮助! 我没有考虑过系统调用本身就是问题,如果只是它对定义的字符串没有用,我会更加怀疑。

根据英特尔有关syscall指令的手册,不是内核会破坏rcx和r11,而是CPU会这样做,因为它会将指令指针保存到前者,并将标志保存到后者。 sysret之后恢复它们以继续正常的程序流程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值