【问题标题】:cmp assembly language instruction - gas formatcmp汇编语言指令-gas格式
【发布时间】:2012-12-29 00:41:10
【问题描述】:

我正在将 32 位和 64 位汇编语言文件从 gas 转换为 MASM 格式,并且在我的代码中遇到了一条似乎完全有问题的指令。我的意思是,我认为汇编器无法知道操作数的大小,指令是否从内存中获取 8、16、32 或 64 位来执行比较。这是说明:

  • cmp $0, 8(%rsp)

如果指令是以下指令之一,汇编器可以根据寄存器计算出要获取和比较的内存操作数的大小:

  • cmp %rax, 8(%rsp)
  • cmp %eax, 8(%rsp)
  • cmp %ax, 8(%rsp)

我原以为指令需要是 cmpb、cmpw、cmpl、cmpq……但不,我的程序只用 cmp 指令就可以很好地组装它。不幸的是,我不记得这段代码在做什么,而且非常不明显......所以解决这个问题的更简单方法是知道指令在做什么。

有人知道吗?任何人都明白为什么这种语法(未指定操作数大小/类型)甚至允许使用直接操作数?

【问题讨论】:

  • 组装的时候选哪个?
  • 这是我的问题。我不知道!
  • 最简单的判断方法是先用gas组装,再用objdump拆。 (操作数大小在几年前默认为 32 位,并且有一个警告。我不确定它现在是什么,在 64 位代码中)
  • 但是在查看反汇编后,它似乎正在获取一个 32 位操作数。但是为什么,特别是因为这是一个 64 位模式程序和 64 位汇编语言,并且指令中指定的唯一寄存器是 %rsp,它是一个 64 位寄存器。
  • 看起来那样。只要我能确定,我就没事。但这不是一个非常危险的情况吗?我的意思是,gas 语法在使类型清晰方面非常过分。

标签: assembly x86-64 gnu-assembler att cmp


【解决方案1】:

它必须有某种默认值。我在我的机器上试了一下,上面写着as是:

Apple Inc version cctools-836, GNU assembler version 1.38

我得到了这些结果:

$ cat example.s 
    cmp $0, 8(%rsp)
$ make example.o
as   -o example.o example.s
$ otool -tV example.o
example.o:
(__TEXT,__text) section
0000000000000000    cmpl    $0x00,0x08(%rsp)

所以在我的机器上,它选择了cmpl。使用 gcc 而不是 as 给了我相同的结果,但使用 clang 产生了您期望的错误:

$ clang -c example.s 
example.s:1:2: error: ambiguous instructions require an explicit suffix (could be 'cmpb', 'cmpw', 'cmpl', or 'cmpq')
 cmp $0, 8(%rsp)
 ^

【讨论】:

  • @honestann,是的,clang 可以为您组装。它必须支持内联汇编。无论如何,机器代码打印机必须支持所有的汇编程序。
  • clang 的名字应该是 gcc++。
  • @Jack,这是什么意思?
  • 可能@Jack 意味着MacOS 带有一个实际上很clang 的g++ 命令。因此,如果您想要 GNU Compiler Collection,MacOS 会欺骗您。不过,这并不是说明这一事实的一种非常有用的方式。
  • 顺便说一句,像 NASM 这样的优秀汇编程序拒绝组装这样的模棱两可的情况,需要一个大小说明符。可以说,GAS / clang 接受这个错误,而不是要求 cmpqcmplcmpwcmpb 用于立即的内存操作数。但是 IDK 是否可以在不破坏现有代码的情况下进行更改。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多