【问题标题】:Delay when running asm program with named variables使用命名变量运行 asm 程序时延迟
【发布时间】:2020-08-10 03:31:09
【问题描述】:

我有以下程序将两个数字相乘:

.globl main

main:
    # Store the two numbers temporarily in ebx, ecx
    mov $7,     %ebx
    mov $14,     %ecx
    # clear out eax and add ebx (7) to it ecx (14) times
    mov $0,     %eax
multiply_step:
    add %ebx,   %eax
    dec %ecx
    jnz multiply_step
    ret

但是,如果我为 147 添加变量,无论出于何种原因,程序运行大约需要一秒钟,这似乎有点奇怪(上面的程序是瞬时的)--

.globl main
.globl x,y
x:  .byte 7
y:  .byte 14

main:
    mov x,     %ebx
    mov y,     %ecx
    mov $0,     %eax
multiply_step:
    add %ebx,   %eax
    dec %ecx
    jnz multiply_step
    ret

为什么这个程序需要更长的时间才能运行?我将两者都调用为:

$ gcc m2.s -o m2 && ./m2; echo $?
# 98

【问题讨论】:

  • 您可以使用调试器查看您在寄存器中获得的值;这是清楚了解这里发生的事情的简单方法。

标签: assembly x86-64 att


【解决方案1】:

变量 x 是一个字节,但是您将 4 个字节移动到 ebx,所以 ebx 没有值 7。加载到 ebx 的实际值是 0x1d8b0e07。同样,ecx 中的值类似于 0x011d8b0e,因此您可以看到为什么您的循环比 0x0e 时花费的时间长得多。

尽管有这个错误,但结果的低字节是一样的。

要将这些字节值加载到 32 位寄存器中,请使用:

movzbl x, %ebx
movzbl y, %ecx

该指令从内存中读取一个字节,将其零扩展为 32 位,并将结果放入目标寄存器。

或者在 64 位代码中,就像您在其他问题中使用的那样,RIP 相对寻址更有效,并且可以在现代 PIE 可执行文件中工作:

movzbl x(%rip), %ebx
movzbl y(%rip), %ecx

【讨论】:

  • 你怎么知道ebx中的值是0x1d8b0e07,还是你只是编了一个以07结尾的数字?
  • 不,我当然不会那样做! :-) 不过,我没有完全正确,因为我不知道这是 64 位代码。它应该是 0x1c8b0e07。 x后面的下一个字节是y,也就是14。接下来的两个字节是main的第一条指令的前两个字节mov x, %ebx,64位模式下是8b 1c 25 xxxxxxxx,其中xxxxxxxx是地址的x。 (如果是 32 位代码,则为 8b 1d xxxxxxxx。)
  • 太棒了,谢谢。出于好奇,您是如何亲自学习组装并变得如此出色的?似乎有很多路径(不像像“学习python”这样更容易/主流的人)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-05
  • 1970-01-01
  • 1970-01-01
  • 2014-06-22
相关资源
最近更新 更多