2017-10-18 259 views
0

我试图将我的C代码转换为x86-64。我的目标是扭转链接列表。传入的两个参数是头部ptr和偏移量以获取指针字段的地址(即指向列表中下一个节点的指针)。将C代码转换为x86-64程序集

据我所知,头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

是否有这样一个看似无用的练习的好理由? –

+5

有很好的工具:C编译器。他们中的许多人可以选择发送汇编代码,而那些不能与反汇编人员配对的选项。 –

+0

很高兴有人同意这是一个无用的练习。我需要完成一个班级任务,但过去几天我一直陷入困境。 – Ryan

回答

2

我不愿意发布我作为编写此答案的一部分而创建的重新工作的代码。你不会学到任何东西。

因此,这里有您可能要修复启动一些事情:

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,以便在对其进行解引用之前检查rdi是否为空。

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

7)“将偏移移入寄存器”说什么?偏移量已经在寄存器中:rsi。为什么要在r12中制作副本?

8)第一次你“检查下一个ptr不为空”,你刚刚添加了偏移量的值。除非你的抵消是零,这不会做你想要的。另见#6。

9)“添加抵消rax来获得下一个ptr”只做一次(即在循环外)。列表中的每个指针都不需要添加这个偏移量吗?

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