2

我正在使用 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    ;<-----uncomment this to print ok!

    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 替换

4

2 回答 2

5

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

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

最好的,弗兰克

于 2012-07-23T18:48:08.973 回答
2

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

为了在 64 位任务中进行系统调用,必须使用“新”系统调用接口。系统调用本身是通过syscall指令完成的。内核销毁寄存器rcxr11. 系统的编号在寄存器中指定,rax而调用的参数传入rdirsirdxr10和。请记住,系统调用的数量与 32 位模式中的不同。您可以在 中找到它们,该位置通常位于您的发行版存储它的位置或任何位置。r8r9unistd_64.h/usr/include/asm

于 2012-07-23T20:09:48.897 回答