assembly 反转数组并以x86-64格式打印

yrefmtwq  于 2022-11-13  发布在  其他
关注(0)|答案(1)|浏览(116)

我试图打印一个数组,反转它,然后再打印一次。我设法打印了一次。我也可以连续两次调用 _printy,它也能工作。但是代码被 _reverse 函数中断。它没有分段错误,退出代码24(我在网上查了一下,但这似乎意味着已经超过了文件描述符的最大数量,我不能理解这在这个上下文中的含义)。我使用了调试器,循环逻辑似乎是有意义的。
我没有在RDI中传递数组,因为 _printy 在退出时会恢复该寄存器的内容。我还尝试在调用 _reverse 之前将其直接加载到RDI中,但这并不能解决问题。
我不知道出了什么问题。你知道吗?

BITS 64
DEFAULT REL

; ------------------------------------- 
; ------------------------------------- 
;             PRINT LIST 
; -------------------------------------
; -------------------------------------

%define SYS_WRITE               0x02000004
%define SYS_EXIT                0x02000001
%define SYS_OPEN                0x02000005
%define SYS_CLOSE               0x02000006
%define SYS_READ                0x02000003

%define EXIT_SUCCESS        0
%define STDOUT                  1

%define LF                          10
%define INT_OFFSET      48

section .text
    extern _printf
    extern _puts
    extern _exit

    global _main

_main:
    push rbp
    lea rdi, [rel array]

    call _printy
    call _reverse
    call _printy

    pop rbp 
    call _exit

_reverse:
    push rbp
    lea rsi, [rdi + 4 * (length - 1) ]
    
    .LOOP2:
        cmp rdi, rsi
        jge .DONE2
        
        mov r8, [rdi]
        mov r9, [rsi]

        mov [rdi], r9 
        mov [rsi], r8   

        add rdi,4 
        sub rsi,4 

        jmp .LOOP2

    .DONE2:
        xor rax, rax
        lea rdi, [rel array]
        pop rbp
        ret
        

_printy:
    push rbp

    xor rcx, rcx
    mov r8, rdi

    .loop:
        cmp rcx, length
        jge .done
        
        push rcx
        push r8

        lea rdi, [rel msg]
        mov rsi, [r8 + rcx * 4]
        xor rax, rax
        call _printf
        
        pop r8
        pop rcx

        add rcx, 1
        jmp .loop

    .done: 
        xor rax, rax
        lea rdi, [rel array]
        pop rbp
        ret

section .data
    array: dd 78, 2, 3, 4, 5, 6
    length: equ ($ - array) / 4
    msg: db "%d => ", 0

使用调试器中的一些信息进行编辑

单步执行 _printy 函数时,一旦到达_printf调用,将发出以下消息。

* thread #1, queue = 'com.apple.main-thread', stop reason = step over failed (Could not create return address breakpoint.)
    frame #0: 0x0000000100003f8e a.out`printf
a.out`printf:
->  0x100003f8e <+0>: jmp    qword ptr [rip + 0x4074]  ; (void *)0x00007ff80258ef0b: printf
    0x100003f94:      lea    r11, [rip + 0x4075]       ; _dyld_private
    0x100003f9b:      push   r11
    0x100003f9d:      jmp    qword ptr [rip + 0x5d]    ; (void *)0x00007ff843eeb520: dyld_stub_binder

我不是Maven,但在网上快速研究后得出以下结论
在执行“thread step-out”命令期间,检查我们将要放置断点的内存是否可执行。以前,如果当前函数具有非标准堆栈布局/ABI,并且在返回地址通常所在的位置具有有效的数据指针,写入断点时将发生数据损坏。这可能导致错误报告的崩溃或程序状态的无提示损坏。现在,如果上述检查失败,命令将安全地中止。
因此,这毕竟不是问题(我也能够跟踪printf调用的执行)。但这确实是我能够从调试器中提取的唯一可理解的信息。在一些相当晦涩(对我来说)的函数调用中,我深入了解到这一点

* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
    frame #0: 0x00007ff80256db7f libsystem_c.dylib`flockfile + 10
libsystem_c.dylib`flockfile:
->  0x7ff80256db7f <+10>: call   0x7ff8025dd480            ; symbol stub for: __error
    0x7ff80256db84 <+15>: mov    r14d, dword ptr [rax]
    0x7ff80256db87 <+18>: mov    rdi, qword ptr [rbx + 0x68]
    0x7ff80256db8b <+22>: add    rdi, 0x8
Target 0: (a.out) stopped.
(lldb) 
Process 61913 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = instruction step into
    frame #0: 0x00007ff8025dd480 libsystem_c.dylib`__error

这是_printf中发生的函数调用之一。
如果我还能做些什么,请再问一些问题。

lnlaulya

lnlaulya1#

您的数组由int32数字组成,在nasm术语中也称为dd,但您的交换操作在64位数字上:

mov r8, [rdi]
    mov r9, [rsi]

    mov [rdi], r9 
    mov [rsi], r8

假设您没有进行一些疯狂的优化,即同时交换一对元素,您希望它保持为32位:

mov r8d, [rdi]
    mov r9d, [rsi]

    mov [rdi], r9d 
    mov [rsi], r8d

相关问题