首页 文章

将C代码转换为x86-64程序集

提问于
浏览
0

我正在尝试将我的C代码转换为x86-64 . 我的目标是扭转链表 . 传入的两个参数是head ptr和偏移量,以获得指针字段的地址(即指向列表中下一个节点的指针) .

根据我的理解,head ptr通过rdi寄存器传入,偏移量通过rsi寄存器传入 . 当它到达“mov rcx,[rbx]”这一行时,我一直遇到分段错误 . 当它只是“mov rcx,rbx”并且后面的行从“mov [rbx],rdx”变为“mov rbx,rdx”时,分段故障消失了 . 但是,我最终陷入了无限循环,因为它只是一遍又一遍地分配相同的值 .

当我跟随我的C代码时,x86-64中的所有逻辑都对我有意义,所以我真的处于停滞状态 . 有任何想法吗?这是我第一次使用x86-64 .

.intel_syntax noprefix
.text
.global reverse_asm_64

reverse_asm_64:
push rbx
push r12

mov rax, 0x0
#headptr
mov rbx, rax
#nextptr
mov rcx, rax
#new_headptr
mov rdx, rax
#head
mov rax, [rdi]

#checks if head is null
cmp rax, 0
je null_ret

#move offset into a register
mov r12, rsi
add rax, r12
#add offset to rax to get the next ptr
mov rbx, rax

while_start:

#checks that next ptr isn't null
cmp rbx, 0x0
je while_done

#setting the next ptr
mov rcx, [rbx]

# *headptr = new_headptr
mov [rbx], rdx

#new_headptr = headptr
mov rdx, rbx

#sets headptr to nextptr
mov rbx, rcx

jmp while_start

while_done:
mov rax, rdx
sub rax, rsi

null_ret:
pop r12
pop rbx
ret

1 回答

  • 3

    我不愿意将我创建的重新编写的代码发布为编写此答案的一部分 . 你不会那样学习任何东西 .

    所以,这里有一些你可能想要开始修复的事情:

    1)鉴于linux有~7个寄存器你可以用于刮擦,似乎没有必要推/弹rbx和r12 . 使用其他不需要保存的寄存器 .

    2)看起来你正在将评论放在他们描述的代码之后( #headptr 等) . 这不是阅读代码的人所期望的 . 最常见的是要么将它放在线上,要么(特别是在汇编程序中)放在同一行上 .

    3)C中的常见做法是在使用它们之前始终将所有变量(尤其是指针)清零 . 然而,在asm中则不那么重要 . 特别是当下一个语句要为同一个寄存器分配不同的值时 . 这不是C中的问题,因为编译器的优化器将简单地丢弃冗余初始化器 . 但是汇编程序没有优化器,所以这只是浪费空间/周期 . 只有零事物必须归零 .

    4)归零寄存器时,请使用 xor eax, eax 而不是 mov . 它更小/更快 .

    5)如果使用 head_ptr = reverse_asm_64(head_ptr, 16) 调用代码,则需要在解除引用之前检查rdi以查看它是否为null .

    6)在asm中,你应该使用 test rdi, rdi 来查看rdi是否为零而不是 cmp rdi, 0 . 它更小/更快 .

    7)“将偏移移入寄存器”说什么?偏移量已经在寄存器中:rsi . 为什么要在r12中复制一份?

    8)第一次“检查下一个ptr是否为空”时,您刚刚将偏移量添加到该值 . 除非您的偏移量为零,否则这不符合您的意图 . 另见#6 .

    9)“向rax添加偏移量以获得下一个ptr”仅执行一次(即在循环外部) . 列表中的每个指针都不需要添加此偏移量吗?

    还有更多,但这是9项 . 似乎足够开始 .

相关问题