我想使用气体宏在装配函数中动态创建一组标签.我想做这样的事情:
.macro set_up_jumptab_entry prefix, from=0, to=10
.quad \prefix_\item
.if \to-\from
set_up_jumptab_entry \prefix,"(\from+1)",\to
.endif
.endm
set_up_jumptab_entry myfunc 0 10
这里\ prefix_\item就像myfunction_7.现在,我可以找到许多递归调用的例子,但我还没有找到一个涉及传入宏参数的标签连接.天然气的记录很少,所以回答这个问题对我来说很难.
X86 GNU Assembly上的宏有什么问题?它表示符号S在链接期间未定义.
.macro S size=40
\size
.endm
Run Code Online (Sandbox Code Playgroud)
我正在使用它
mov %eax, S
Run Code Online (Sandbox Code Playgroud) 我读过这个页面,其中包含了针对GAS的英特尔和AT&T语法之间的差异的良好列表,但它没有涵盖仅指定具有位移的地址的情况.
在这里,我用AT&T语法组装了四行:
.text
0000 48C7C008000000 mov $8, %rax
0007 488B042508000000 mov (8), %rax
000f 4889F0 mov %rsi, %rax
0012 488B06 mov (%rsi), %rax
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,前两行是不同的.第一个将立即值8移动到rax中,第二个将地址8的内容移动到rax中.但是使用Intel语法我会得到以下奇怪的行为:
.text
.intel_syntax
0000 48C7C008000000 mov %rax, 8
0007 48C7C008000000 mov %rax, [8]
000e 4889F0 mov %rax, %rsi
0011 488B06 mov %rax, [%rsi]
Run Code Online (Sandbox Code Playgroud)
这里第一行和第二行汇编到相同的机器代码!首先我认为方括号是错误的,所以我在测试中添加了第三行和第四行,并且方括号对于内存寻址至少在涉及寄存器时起作用.
我读过的所有文档都显示了至少有一个基址或索引寄存器的内存寻址示例,有时还有一个比例和位移,但从不仅仅是位移.
我确实有使用NASM汇编程序的英特尔语法经验,它可以区分mov rax, 8和mov rax, [8].
这是GAS中的错误吗?或者如果没有,我如何指定NASM的等效物mov rax, [8]?
我意识到指定一个仅位移地址可能并不常见,但我希望通过这种语法完全理解所有内存寻址形式.
我编写了一个基本的C程序,它定义了一个整数变量x,将其设置为零并返回该变量的值:
#include <stdio.h>
int main(int argc, char **argv) {
int x;
x = 0;
return x;
}
Run Code Online (Sandbox Code Playgroud)
当我使用objdump(使用gcc在Linux X86-64上编译)转储目标代码时:
0x0000000000400474 <main+0>: push %rbp
0x0000000000400475 <main+1>: mov %rsp,%rbp
0x0000000000400478 <main+4>: mov %edi,-0x14(%rbp)
0x000000000040047b <main+7>: mov %rsi,-0x20(%rbp)
0x000000000040047f <main+11>: movl $0x0,-0x4(%rbp)
0x0000000000400486 <main+18>: mov -0x4(%rbp),%eax
0x0000000000400489 <main+21>: leaveq
0x000000000040048a <main+22>: retq
Run Code Online (Sandbox Code Playgroud)
我可以看到函数序言,但在我们在地址处将x设置为0之前,0x000000000040047f有两条指令将%edi和%rsi移动到堆栈上.这些是为了什么?
另外,与将x设置为0的情况不同,GAS语法中显示的mov指令没有后缀.
如果未指定后缀,并且指令没有存储器操作数,则GAS根据目标寄存器操作数的大小推断操作数大小.
在这种情况下,是-0x14(%rsbp)和-0x20(%rbp)两个内存操作数和它们的大小是什么?由于%edi是32位寄存器,因此移动到32位,-0x14(%rsbp)而由于%rsi是64位寄存器,64位移动到%rsi,-0x20(%rbp)?
我知道该.ascii指令不会在字符串的末尾添加空字符.该.asciz指令用于此目的.但是,我不知道该.string指令是否在字符串的末尾放置一个空字符.如果确实如此,那么指令.asciz和.string指令之间的区别是什么?对我来说,同时具有.ascii和.string似乎是多余的.
我用AT&T语法编写了一个程序,用于GNU汇编程序:
.data
format: .ascii "%d\n"
.text
.global main
main:
mov $format, %rbx
mov (%rbx), %rdi
mov $1, %rsi
call printf
ret
Run Code Online (Sandbox Code Playgroud)
我使用GCC来组装和链接:
gcc -o main main.s
我用这个命令运行它:
./主要
当我运行程序时,我得到一个seg错误.通过使用gdb,它说printf没有找到.我试过".extern printf",但是没有用.有人建议我应该printf在RET之前存储堆栈指针并在RET之前恢复,我该怎么做?
无论我如何努力谷歌,我似乎都找不到(相对)易于遵循的关于如何在 Mac 上安装 GNU 汇编器的说明。
我知道我可以使用gcc -c(Mac 上的 Apple Clang)来汇编.s/.S文件,但我想使用实际的 GNU Binutils as。
我的工具链是arm-gcc的最新版本.
我在汇编文件中有一段代码,必须有条件地包含/组装.
.ifdef MACRO_FROM_CMDLINE
Assembly instr1
Assembly instr2
.endif
Run Code Online (Sandbox Code Playgroud)
封装代码是最近添加的.
我试过了两个:
gcc -x assembler-with-cpp --defsym MACRO_FROM_CMDLINE=1 <along with other necessary options>
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 <along with other necessary options>
Run Code Online (Sandbox Code Playgroud)
的-D在"无效标识符无效代码"和结果"无.endif注意.如果"错误.
将--defsym在结果"MACRO_FROM_CMDLINE = 1:没有这样的文件或目录","无法识别的选项--defsym"的错误.
以下是Intel语法中的一些汇编代码:
// Jump to done if rsi >= rax.
cmp rsi, rax
jae done
Run Code Online (Sandbox Code Playgroud)
这对我的大脑有意义:如果rsi"高于或等于"rax,则跳转,匹配指令中参数的顺序cmp.将其与GNU语法进行比较:
// Jump to done if rsi >= rax.
cmp %rax, %rsi
jae done
Run Code Online (Sandbox Code Playgroud)
这每次伤害我的大脑.它没有帮助,当我来到这个新的后一段时间不写汇编代码我去看看的语义cmp
,并jae在Intel手册,发现这一切都在"第一","第二"操作,来表述其与我面前在屏幕上看到的不符.
结束抱怨.我的问题:
有没有其他方式表达cmp或jaeGNU汇编程序,以便操作数的顺序cmp与逻辑比较匹配jae?
假设(1)的答案是否定的,是否有人有一个很好的方式让我看看这个,以便我能记住下次它是如何工作的?还有比"GNU倒退"更好的东西吗?
请注意,我不是要问如何在GNU汇编程序中使用Intel语法; 我知道这是可能的.我正在使用现有的GNU语法代码库,并且正在寻求一些助记符或其他方式来帮助我保持这一点.
我已经根据MOTOROLA M68000 FAMILY Programmer\xe2\x80\x99s Reference Manual编写了自己的Sega Mega Drive ROM 反汇编程序。拆卸了相当大的 ROM 块后,我尝试使用VASM重新组装这个拆卸的输出,因为它可以使用其语法模块接受摩托罗拉汇编语法。mot
现在,对于绝大多数重组来说,这种方法效果很好,但是,对于具有由“带索引(8 位位移)模式的程序计数器间接”定义的有效地址的操作,存在一个问题。鉴于我现在才学习 Motorola 68000 组装,我想确认我的理解并问:这些操作的正确语法是什么?
\n例如,如果我有两个词:
\n4ebb 0004\nRun Code Online (Sandbox Code Playgroud)\n我将其解释为JSR目标目的地是以下各项的总和:
pc0x04d0(鉴于我将自己限制在 68000,我在扩展字中省略了对sizeand的任何考虑scale)。\n根据参考手册中如何描述此寻址模式,我将其发出为:
jsr ($04,pc,d0)\nRun Code Online (Sandbox Code Playgroud)\n但是,当我将其反馈回 VASM 时,它会发出以下错误:
\nerror 2030 in line X of "XXXX.asm": displacement out of range\n> jsr ($04,pc,d0)\nRun Code Online (Sandbox Code Playgroud)\n这似乎是一个非常奇怪的错误,因为由于寄存器的使用,位移直到运行时才能知道 …
gnu-assembler ×10
assembly ×9
gcc ×3
x86 ×3
disassembly ×2
gnu ×2
68000 ×1
c ×1
directive ×1
intel-syntax ×1
linux ×1
macos ×1
x86-64 ×1