逆转阵列并在x86-64中打印

发布于 2025-02-10 21:56:14 字数 3695 浏览 2 评论 0原文

我正在尝试打印一个阵列,将其倒转,然后再次打印。我设法打印一次。我还可以连续2次打电话给 _printy ,并且有效。但是代码会用 _reverse 函数中断。它没有segfault,而是使用代码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 函数,给出以下msg,一旦接触到_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

我不是专家,但是在线快速研究导致了以下内容

在“线程渐进式”命令期间,检查我们要放置断点的内存是否可执行。以前,如果当前函数具有非标准的堆栈布局/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
中发生的函数调用之一。
问进一步的问题,如果我还能做更多的事情。

I am trying to print an array, reverse it, and then print it again. I manage to print it once. I can also make 2 consecutive calls to _printy and it works. But the code breaks with the _reverse function. It does not segfault, it exits with code 24 (I looked online but this seems to mean that the maximum number of file descriptors has been exceeded, and I cannot get what this means in this context). I stepped with a debugger and the loop logic seems to make sense.

I am not passing the array in RDI, because _printy restores the content of that register when it exits. I also tried to load it directly into RDI before calling _reverse but that does not solve the problem.
I cannot figure out what the problem is. Any idea?

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

Edit with some info from the debugger

Stepping into the _printy function gives the following msg, once reaching the call to _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

I am not an expert, but a quick research online led to the following

During the 'thread step-out' command, check that the memory we are about to place a breakpoint in is executable. Previously, if the current function had a nonstandard stack layout/ABI, and had a valid data pointer in the location where the return address is usually located, data corruption would occur when the breakpoint was written. This could lead to an incorrectly reported crash or silent corruption of the program's state. Now, if the above check fails, the command safely aborts.

So after all this might not be a problem (I am also able to track the execution of the printf call). But this is really the only understandable piece of information I am able to extract from the debugger. Deep in some quite obscure (to me) function calls I reach this

* 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

This is one of the function calls happening in _printf.
Ask further questions if there is something more I can do.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

擦肩而过的背影 2025-02-17 21:56:15

您的数组由int32编号aka dd在NASM术语中,但是您的交换在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 

Your array consists of int32 numbers aka dd in nasm terminology, but your swap operates on 64 bit numbers:

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

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

Assuming you were not after some crazy optimizations where you swap a pair of elements simultaneously you want this to remain in 32 bits:

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

    mov [rdi], r9d 
    mov [rsi], r8d 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文