是否可以使用英特尔语法为 AMD 处理器编写 ASM 代码?
Is it possible to code ASM code in Intel Syntax for AMD processors?
使用 Intel Syntax 或 AT&T 独立于 CPU 微架构?我的意思是,编译器的任务是将代码(独立地,如果它是 AT&T 或 Intel 语法)转换为二进制代码,以便可以使用任何语法编写代码?
语法独立于 CPU 体系结构。例如。在 gcc or g++ 中,可以使用任何一种语法。默认是AT&T格式,但是在inline assembly中加入".intel_syntax"
可以使用intel语法。
示例代码
int main() {
__asm__ __volatile__ (
".intel_syntax noprefix\n"
"jmp farlabel\n"
"mov EAX,EAX\n"
"farlabel:\n"
"mov EAX,EAX\n"
".att_syntax prefix\n"
);
return 0;
}
(source)
Pragma noprefix
表示寄存器名前不需要加%
。 .att_syntax
切换回 AT&T 语法,因为生成的其余汇编代码采用这种风格。
根据black
的评论我检查了如果我编译上面的小代码会调用哪些程序。实际上 gcc 调用 cc1plus
生成 .s
文件(这是汇编代码),然后调用 as
生成 .o
(对象)文件,然后调用collect2
(我假设这会在用户代码周围添加动态加载程序和其他机制),然后将 ld
与 link 代码一起调用并创建可执行文件。
如果调用gcc -S x.cc
,那么它会在汇编代码生成后立即停止,所以可以看到临时文件。这是生成的代码:
.file "x.cc"
.text
.globl* main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
#APP
# 9 "x.cc" 1
.intel_syntax noprefix
jmp farlabel
mov EAX,EAX
farlabel:
mov EAX,EAX
.att_syntax prefix
# 0 "" 2
#NO_APP
movl [=11=], %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
这里两种风格混合...
据此link,汇编语法有两个主要分支。
x86 assembly language has two main syntax branches: Intel syntax,
originally used for documentation of the x86 platform, and AT&T
syntax.1 Intel syntax is dominant in the MS-DOS and Windows world,
and AT&T syntax is dominant in the Unix world, since Unix was created
at AT&T Bell Labs.[2]
两者均可用于为基于 CPU 的 x86 编写汇编程序。汇编程序将采用该语法并将其转换为 OS 可以加载并且 CPU 可以执行的二进制格式。
因此,至少在理论上,只要汇编器能够理解所提供的语法,用任何一种语法编写的两个程序都应该编译成完全相同的二进制代码。
您使用哪种格式取决于您的汇编程序支持什么。只是为了进一步混淆事情,还有其他变体,例如 nasm 相当流行。
使用 Intel Syntax 或 AT&T 独立于 CPU 微架构?我的意思是,编译器的任务是将代码(独立地,如果它是 AT&T 或 Intel 语法)转换为二进制代码,以便可以使用任何语法编写代码?
语法独立于 CPU 体系结构。例如。在 gcc or g++ 中,可以使用任何一种语法。默认是AT&T格式,但是在inline assembly中加入".intel_syntax"
可以使用intel语法。
示例代码
int main() {
__asm__ __volatile__ (
".intel_syntax noprefix\n"
"jmp farlabel\n"
"mov EAX,EAX\n"
"farlabel:\n"
"mov EAX,EAX\n"
".att_syntax prefix\n"
);
return 0;
}
(source)
Pragma noprefix
表示寄存器名前不需要加%
。 .att_syntax
切换回 AT&T 语法,因为生成的其余汇编代码采用这种风格。
根据black
的评论我检查了如果我编译上面的小代码会调用哪些程序。实际上 gcc 调用 cc1plus
生成 .s
文件(这是汇编代码),然后调用 as
生成 .o
(对象)文件,然后调用collect2
(我假设这会在用户代码周围添加动态加载程序和其他机制),然后将 ld
与 link 代码一起调用并创建可执行文件。
如果调用gcc -S x.cc
,那么它会在汇编代码生成后立即停止,所以可以看到临时文件。这是生成的代码:
.file "x.cc"
.text
.globl* main
.type main, @function
main:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
#APP
# 9 "x.cc" 1
.intel_syntax noprefix
jmp farlabel
mov EAX,EAX
farlabel:
mov EAX,EAX
.att_syntax prefix
# 0 "" 2
#NO_APP
movl [=11=], %eax
popl %ebp
.cfi_restore 5
.cfi_def_cfa 4, 4
ret
.cfi_endproc
.LFE0:
.size main, .-main
.ident "GCC: (Debian 4.7.2-5) 4.7.2"
.section .note.GNU-stack,"",@progbits
这里两种风格混合...
据此link,汇编语法有两个主要分支。
x86 assembly language has two main syntax branches: Intel syntax, originally used for documentation of the x86 platform, and AT&T syntax.1 Intel syntax is dominant in the MS-DOS and Windows world, and AT&T syntax is dominant in the Unix world, since Unix was created at AT&T Bell Labs.[2]
两者均可用于为基于 CPU 的 x86 编写汇编程序。汇编程序将采用该语法并将其转换为 OS 可以加载并且 CPU 可以执行的二进制格式。
因此,至少在理论上,只要汇编器能够理解所提供的语法,用任何一种语法编写的两个程序都应该编译成完全相同的二进制代码。
您使用哪种格式取决于您的汇编程序支持什么。只是为了进一步混淆事情,还有其他变体,例如 nasm 相当流行。