gpt4 book ai didi

assembly - 在汇编中将十进制转换为 ASCII/二进制

转载 作者:行者123 更新时间:2023-12-02 22:13:45 25 4
gpt4 key购买 nike

我正在尝试将给定的十进制数转换为 32 个字符的二进制数,但我的代码不断给出错误的答案

我正在尝试转换为二进制的数字

aLength     db  21

我使用的变量

two         dq      2
tempString resb 33

我尝试将 aLength (21) 除以 2 32 次并将所有余数堆叠起来,但它不起作用

这是我的代码

mov rax,0
mov eax,byte[aLength]
mov rcx,32

lp2:
mov rdx,0
div qword[two]
push rdx
loop lp2
mov rsi,tempString
mov rcx,2

lp3:
pop rax
add al,"0"
mov byte[rbx],al
inc rbx
loop lp3
mov byte[rbx],NULL

最佳答案

debug你的代码在一起。

调试是您应该必须自己完成的事情,因为编写代码只是故事的一半。
老实说,我认为这个问题会被否决,因为实际上恰恰相反,人们似乎希望得到答案。

现在,您提出了很多类似的问题4,这表明您完全缺乏调试技能。
因此,我们不会告诉您代码中易于发现和调试的错误,而是进行调试,所以也许您会学到一些东西。

我们将使用 GDB1。我从您的代码2开始,制作了一个针对 ELF64 的可汇编版本,并在 Cygwin 上使用 gcc 编译了目标文件。

<小时/>

让我们首先检查我们的值是否已正确加载。
单步执行前两条指令,即设置 RAX 的指令。

   ┌───────────────────────────────────────────────────────────────────────────┐
B+ │0x1004010e0 <WinMain> mov $0x0,%eax │
│0x1004010e5 <WinMain+5> mov 0xf25(%rip),%eax # 0x10040201│
│0x1004010eb <WinMain+11> mov $0x20,%ecx │
│0x1004010f0 <lp2> mov $0x0,%edx │
>│0x1004010f5 <lp2+5> divq 0xf15(%rip) # 0x100402011 <tw│
│0x1004010fc <lp2+12> push %rdx │
│0x1004010fd <lp2+13> loop 0x1004010f0 <lp2> │
│0x1004010ff <lp2+15> movabs $0x100407000,%rsi │
│0x100401109 <lp2+25> mov $0x2,%ecx │
│0x10040110e <lp3> pop %rax │
│0x10040110f <lp3+1> add $0x30,%al │
│0x100401111 <lp3+3> mov %al,(%rbx) │
│0x100401113 <lp3+5> inc %rbx │
│0x100401116 <lp3+8> loop 0x10040110e <lp3> │
│0x100401118 <lp3+10> movb $0x0,(%rbx) │
│0x10040111b <lp3+13> retq │
└───────────────────────────────────────────────────────────────────────────┘
native Thread 5100.0x9e4 In: lp2 L?? PC: 0x1004010f5
(gdb) si 4
0x00000001004010f5 in lp2 ()
(gdb) i r rax rcx rdx
rax 0x215 533
rcx 0x20 32
rdx 0x0 0
(gdb)

运送商店!这里发生了什么?
RCXRDX看起来不错,但RAX不行!当然,533 与 21 有很大不同

经过整整十分钟的刮头,我们终于发现第二条指令正在从aLength加载一个DWORD,它是一个字节,所以我们是将一些垃圾放入RAX中。

因此我们更正该行3:

mov al, BYTE [aLength]

我们再次重复之前的调试步骤:

(gdb) i r rax rcx rdx
rax 0x15 21
rcx 0x20 32
rdx 0x0 0

好!
现在我们执行循环的第一次迭代

<小时/>
   ┌───────────────────────────────────────────────────────────────────────────┐
│0x1004010e5 <WinMain+5> mov 0xf25(%rip),%al # 0x100402010│
│0x1004010eb <WinMain+11> mov $0x20,%ecx │
>│0x1004010f0 <lp2> mov $0x0,%edx │
│0x1004010f5 <lp2+5> divq 0xf15(%rip) # 0x100402011 <tw│
│0x1004010fc <lp2+12> push %rdx │
│0x1004010fd <lp2+13> loop 0x1004010f0 <lp2> │
│0x1004010ff <lp2+15> movabs $0x100407000,%rsi │
│0x100401109 <lp2+25> mov $0x2,%ecx │
│0x10040110e <lp3> pop %rax │
│0x10040110f <lp3+1> add $0x30,%al │
│0x100401111 <lp3+3> mov %al,(%rbx) │
│0x100401113 <lp3+5> inc %rbx │
│0x100401116 <lp3+8> loop 0x10040110e <lp3> │
│0x100401118 <lp3+10> movb $0x0,(%rbx) │
│0x10040111b <lp3+13> retq │
└───────────────────────────────────────────────────────────────────────────┘
native Thread 4236.0x12e0 In: lp2 L?? PC: 0x1004010f0
rdx 0x0 0
(gdb) si 3
0x00000001004010f0 in lp2 ()
(gdb) i r rax rcx rdx
rax 0xa 10
rcx 0x1f 31
rdx 0x1 1
(gdb)

一切看起来都不错:RAX 减半,RCX 是 32 减一,RDX 是 21 的最低有效位,即 1。
让我们检查一下堆栈上是否有效地存在这个。

A syntax error in expression, near `%rsp'.
(gdb) x/1dg $rsp
0xffffcb20: 1

不错!

<小时/>

由于循环看起来没问题,我们现在可以跳出循环并检查部分结果

   ┌───────────────────────────────────────────────────────────────────────────┐
│0x1004010dc <__gcc_deregister_frame+12> nop │
│0x1004010dd <__gcc_deregister_frame+13> nop │
│0x1004010de <__gcc_deregister_frame+14> nop │
│0x1004010df <__gcc_deregister_frame+15> nop │
B+ │0x1004010e0 <WinMain> mov $0x0,%eax │
│0x1004010e5 <WinMain+5> mov 0xf25(%rip),%al # 0x1│
│0x1004010eb <WinMain+11> mov $0x20,%ecx │
│0x1004010f0 <lp2> mov $0x0,%edx │
│0x1004010f5 <lp2+5> divq 0xf15(%rip) # 0x10040│
│0x1004010fc <lp2+12> push %rdx │
│0x1004010fd <lp2+13> loop 0x1004010f0 <lp2> │
>│0x1004010ff <lp2+15> movabs $0x100407000,%rsi │
│0x100401109 <lp2+25> mov $0x2,%ecx │
│0x10040110e <lp3> pop %rax │
│0x10040110f <lp3+1> add $0x30,%al │
└───────────────────────────────────────────────────────────────────────────┘
native Thread 4236.0x12e0 In: lp2 L?? PC: 0x1004010ff
(gdb) p/u *(unsigned long long (*)[32])$rsp
$3 = {0 <repeats 27 times>, 1, 0, 1, 0, 1}
(gdb)

寄存器肯定没问题,所以我们只检查推送的值。
正如 GDB 告诉我们的那样,数字 21 已正确转换为 0..010101。

<小时/>

我们现在再次调试下一个循环的第一次迭代:

   ┌───────────────────────────────────────────────────────────────────────────┐
>│0x10040110e <lp3> pop %rax │
│0x10040110f <lp3+1> add $0x30,%al │
│0x100401111 <lp3+3> mov %al,(%rbx) │
│0x100401113 <lp3+5> inc %rbx │
│0x100401116 <lp3+8> loop 0x10040110e <lp3> │
│0x100401118 <lp3+10> movb $0x0,(%rbx) │
│0x10040111b <lp3+13> retq │
│0x10040111c <lp3+14> nopl 0x0(%rax) │
│0x100401120 <__cxa_atexit> jmpq *0x6fbe(%rip) # 0x1004080e4 <│
│0x100401126 <__cxa_atexit+6> nop │
│0x100401127 <__cxa_atexit+7> nop │
│0x100401128 <__cxa_atexit+8> nop │
│0x100401129 <__cxa_atexit+9> nop │
│0x10040112a <__cxa_atexit+10> nop │
│0x10040112b <__cxa_atexit+11> nop │
└───────────────────────────────────────────────────────────────────────────┘
native Thread 4236.0x12e0 In: lp3 L?? PC: 0x10040110e
0x0000000100401116 in lp3 ()
(gdb) si
0x000000010040110e in lp3 ()
(gdb) i r rsi rax rbx rcx
rsi 0x100407000 4299190272
rax 0x30 48
rbx 0x285541 2643265
rcx 0x1 1
(gdb)

哦,快点!
RSI没有增加!而且仅经过一次迭代后,RCX 就为 1。 RAX 不过还可以。

经过整整十分钟的令人沮丧的思考,我们意识到我们在循环中使用EBX,而不是RSI,并且我们设置>RCX 到 2 而不是 32!

我们修复了这些问题:

mov rbx, tempString
mov rcx, 32
<小时/>

最后我们尝试运行程序直到结束。
完成后,我们检查写入的字符串:

(gdb) x/4xg 0x100407000
0x100407000 <tempString>: 0x3030303030303030 0x3030303030303030
0x100407010 <tempString+16>: 0x3030303030303030 0x3130313031303030

考虑到字节顺序是

30 30 30 30 30 30 30 30   30 30 30 30 30 30 30 30   30 30 30 30 30 30 30 30   30 30 30 31 30 32 30 31

确认程序的正确性。

<小时/>

Here again ,您的程序可以使用使用 CF 的相同技巧来简化:

 movzx ebx, BYTE [REL aLength]      ;EBX = Byte to convert
mov rcx, 32 ;RCX = Bits left to convert
mov rdi, tempString ;RDI = Pointer to output string

xor eax, eax
mov al, '0' ;RAX = Aux value

_convert:

shr eax, 1 ;Get rid of RAX bit 0

shl ebx, 1 ;Set CF to the current msb of EBX
rcl eax, 1 ;Shift into RAX the CF

stosb ;Store ASCII digit

sub rcx, 1 ;Repeat
ja _convert

mov BYTE [rdi], cl ;Write NULL TERM
<小时/>

1 因为乞丐不能挑剔。 This cheatsheet会有用的。
2 原来的,不是可疑的补丁。
3 实现可能最丑陋的方式将字节加载到RAX中。
4 正如我在评论中所解释的,你们中的一个问题本质上是这个问题的补充,并且可以非常直接地重复使用。

关于assembly - 在汇编中将十进制转换为 ASCII/二进制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37841370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com