【问题标题】:How to increment value of global variable in assembly in linux如何在linux的程序集中增加全局变量的值
【发布时间】:2018-04-23 15:59:57
【问题描述】:

我正在通过 AES 算法的汇编实现来了解 sbox 和查找表是如何实现/访问的。 理论上我知道,当密钥长度=128bits 时,AES 使用 10 轮。

有一个部分是执行一个循环的 200 行代码(表示 AES 轮次)。

_x86_64_AES_decrypt_compact:


.Ldec_loop_compact:

xorl    0(%r15),%eax
xorl    4(%r15),%ebx
xorl    8(%r15),%ecx
xorl    12(%r15),%edx
leaq    16(%r15),%r15
.
.
.
xorl    %r12d,%ecx
movq    256(%r14),%r13
xorl    %r8d,%ebx
xorl    %r11d,%edx

jmp .Ldec_loop_compact

每次完成一轮 AES 时,我想将全局变量(即 round_var)的值增加 1。 因此,在 1 个块(16 字节)上的 AES 操作结束时,变量的值为 10 和 在 2 个块(2x16 字节)上的 AES 操作结束时,变量的值为 20。

.globl round_var 
round_var:
.long 0

_x86_64_AES_decrypt_compact:


.Ldec_loop_compact:
.
.
.
;increase round_var by 1 
.
.
.
jmp .Ldec_loop_compact

要将 round_var 增加 1 ,我尝试了以下方法

64bit :
        movq    round_var(%rip), %rax
        addq    $1, %rax
        movq    %rax, round_var(%rip)

32bit :
        movl    round_var(%rip), %eax
        addl    $1, %eax
        movl    %eax, round_var(%rip)

由于所有 eax、ebx、ecx、edx 都在该循环中使用,我只是在更新 %eax(或 %rax)寄存器之前添加了这些行,因此它不会影响 AES 操作。

添加这些行后,我可以成功执行以下命令来构建自定义的 openssl。这意味着在编译/汇编期间将这些行添加到正确的位置。

make
sudo make install

但是,我在尝试执行 AES 解密操作时遇到了分段错误。这表明这些行代码在运行时出现了问题。

我怀疑 movl round_var(%rip), %eax 的 %rip 导致了这个分段错误。

如果有人帮助我解决上述问题或使用汇编指令将全局变量 round_var 加 1,那就太好了?

我正在使用 Ubuntu-16.04、Intel(R) Core(TM) i5-7200U CPU @ 2.50GHz 和 Openssl-1.0.2n

提前致谢。

【问题讨论】:

  • 不要将变量放入.text 部分,因为它是只读的。另外,如果您使用的是 x86-64,为什么要将其标记为 arm?
  • @Jester,感谢您的及时回复。那么变量放在哪里呢?
  • @bholanath 如果已初始化则将它们放入.data,否则放入.bss。
  • @fuz: .bss 是零初始化的,不是不确定的。您可以可靠地将它用于static int foo = 0; 之类的变量,编译器当然会这样做。我不喜欢零初始化的“未初始化”一词,因为在其他上下文中(如 C 中的本地变量),同一个词用于表示不确定。例如"变量 bar 在函数 blah blah 中使用未初始化"
  • @fuz,谢谢。当我试图修改在只读部分声明的变量时,出现上述错误。通过在 .bss 或 .data 部分声明变量可以解决问题。我做了如下 - .bss .global round_var round_var: .long 0 我不知道如何在 .data 部分声明全局初始化变量

标签: assembly x86-64


【解决方案1】:

静态变量应该放在.data 部分。为此,请编写:

        .data                 # enter the data section
        .align 4              # align to four bytes
var:    .long 1234            # assemble a 32 bit word with value 1234

您可能还想指定以下内容以帮助调试:

        .type var,@object     # var refers to an object
        .size var,4           # var occupies 4 bytes of storage

如果变量最初的值为零,您可以选择将其放在.bss 部分中以节省二进制文件中的空间。 .bss 部分在二进制中不占用空间,在运行时用零填充。

        .bss                  # enter the bss section
        .align 4              # align to four bytes
var:    .space 4              # allocate four bytes for var

与之前的方法类似,您可能还想指定符号大小和类型以便更好地调试。

作为这个的简写,你可以写

        .lcomm var,4          # align four bytes in .bss for var

第三种选择是将变量定义为通用符号。这会导致来自其他翻译单元的所有具有相同名称的变量与该变量合并,并且对于创建全局变量很有用。简单写

        .comm var,4           # defines var to be a common symbol of size 4

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    • 1970-01-01
    • 2015-07-04
    • 2015-09-08
    相关资源
    最近更新 更多