繁体   English   中英

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

[英]Converting C code to x86-64 assembly

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

据我了解,头部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)鉴于linux拥有约7个寄存器,您可以从头开始使用它,因此似乎不需要推送/弹出rbx和r12。 使用其他不需要保存的寄存器。

2)您似乎在将注释放在描述的代码之后#headptr等)。 不是阅读您的代码的人所期望的。 最常见的是将其放在前面的行中,或者(尤其是在汇编器中)放在同一行上。

3)在C语言中,通常的做法是在使用变量之前始终将所有变量(尤其是指针)清零。 但是,在asm中少了。 尤其是当下一条语句要为同一寄存器分配不同的值时。 在C语言中这不是问题,因为编译器的优化器只会丢弃冗余的初始化器。 但是汇编器没有优化器,因此这只是浪费空间/周期。 只有零的东西必须归零。

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

5)如果使用head_ptr = reverse_asm_64(head_ptr, 16)调用代码, head_ptr = reverse_asm_64(head_ptr, 16)要在取消引用之前检查rdi以查看其是否为空。

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

7)“将偏移量移入寄存器”说什么? 该偏移量已经在寄存器:rsi中。 为什么要在r12中进行复制?

8)第一次“检查下一个ptr不为空”时,您刚刚将偏移量添加到该值。 除非您的偏移量为零,否则这将无法实现您的预​​期。 另请参阅#6。

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM