将C代码转换为x86-64程序集 [英] Converting C code to x86-64 assembly

查看:163
本文介绍了将C代码转换为x86-64程序集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to convert my C code to x86-64. My goal is to reverse a linked list. The two parameters that are passed in are the head ptr and the offset to to get the address of the pointer field (i.e. the pointer to the next node in the list).

据我了解,头部ptr通过rdi寄存器传递,而偏移量通过rsi寄存器传递.当到达"mov rcx,[rbx]"行时,我一直遇到分段错误.当分割错误仅是"mov rcx,rbx"并且其后的行从"mov [rbx],rdx"更改为"mov rbx,rdx"时,故障就消失了.但是,我最终陷入无限循环,因为它总是不断地重复分配相同的值.

From what I understand, the head ptr is passed in through the rdi register, and the offset is passed in through the rsi register. I keep getting a segmentation fault when it reaches the line "mov rcx, [rbx]." The segmentation fault goes away when it's just "mov rcx, rbx" and the line following is changed from "mov [rbx], rdx" to "mov rbx, rdx." However, I end up in an infinite loop because it keeps simply assigning the same values over and over again.

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

When I'm following along with my C code, all of the logic in the x86-64 makes sense to me, so I'm really at a standstill. Any ideas? This is my first time using 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

推荐答案

我不愿意发布我在编写此答案时创建的经过重新处理的代码.您不会那样学习任何东西.

I'm reluctant to just post the re-worked code I created as part of writing this answer. You aren't going to learn anything that way.

因此,以下是您可能需要修复以开始的一些事情:

So, here are some things you might want to fix to start:

1)鉴于linux有大约7个寄存器,您可以从头开始使用它,所以似乎不需要压入/弹出rbx和r12.使用不需要保存的其他寄存器.

1) Given that linux has ~7 registers you can use for scratch, there doesn't seem to be a need to push/pop rbx and r12. Use other registers that don't need to be saved.

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

2) It looks like you are putting the comments after the code they describe (#headptr et al). This is not what people who read your code are going to expect. Most common is either to put it on the line before, or (especially in assembler) on the same line.

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

3) It is common practice in C to always zero out all the variables (especially pointers) before you use them. However, less so in asm. Especially when the next statement is going to assign a different value to that same register. This isn't a problem in C since the compiler's optimizers will simply discard the redundant initializer. But assembler doesn't have optimizers, so this is just a waste of space/cycles. Only zero things that must be zeroed.

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

4) When zeroing a register, use xor eax, eax instead of mov. It smaller/faster.

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

5) If your code is called with head_ptr = reverse_asm_64(head_ptr, 16), you are going to want to check rdi to see if it is null before dereferencing it.

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

6) In asm, you should use test rdi, rdi to see if rdi is zero rather than cmp rdi, 0. It's smaller/faster.

7)将偏移量移入寄存器"说什么?该偏移量已存在于寄存器:rsi中.为什么要在r12中制作副本?

7) "move offset into a register" Say what? The offset is already in a register: rsi. Why make a copy in r12?

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

8) The very first time you "checks that next ptr isn't null", you have just added the offset to the value. Unless your offset is zero, this isn't going to do what you intend. See also #6.

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

9) The "add offset to rax to get the next ptr" is only done once (ie outside the loop). Wouldn't each pointer in the list need to have this offset added?

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

There's more, but that's 9 items. Seems like enough for a start.

这篇关于将C代码转换为x86-64程序集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆