GNU Assembler (GAS),Microsoft Macro Assembler (MASM),Netwide Assembler (NASM),Flat Assembler (FASM)
等,不同汇编器有不同的汇编语言,GAS
汇编器使用AT&T
汇编语法,MASM
使用Intel
汇编语法,NASM
使用的汇编语法和Intel
汇编语法类似,但比Intel
的简单,每种汇编语法都有自己的手册可以查阅。GAS
的AT&T
语法可以查询GNU Tools Manuals;NASM
的语法可以查询NASM官网。ATT:# 开头
NASM:; 开头
ATT: 十六进制 $0xff
NASM:十六进制 0ffh
ATT:引用寄存器需要加%
NASM:引用寄存器什么都不加
ATT:引用es:di中的值
%es:(%di)
NASM:引用es:di中的值
[es:di]
ATT:在指令后面加X字母
X可选值:
l - 32bit, w - 16bit, b - 8bit
NASM:在立即数或者其它不确定长度的内存地址前加单词X
X可选值:
dword - 32bit, word - 16bit, byte - 8bit
定义一个16bit数据
ATT:
wSectorNo:
.word 0
NASM:
wSectorNo dw 0
将标号wSectorNo处的值读取到ax中
ATT:
movw wSectorNo, %ax // 直接引用
NASM:
mov ax, [wSectorNo]
将标号2处的地址取出,保存到eax中
ATT:加'$'就是取地址
movl $2f, %eax //需要加$
2:
xxxxxxx
NASM:标号本身就是地址
mov dword eax, .2
.2:
xxxxxxx
比较标号bOdd处的1个字节是否为1
ATT:
movb bOdd, %al
cmpb $1, %al
NASM:
cmp byte [bOdd], 1
ax右移4bit
ATT:
shrw $4, %ax
NASM:
shr ax, 4
ATT:
mov src, dst
NASM:
mov dst, src
语法相同
jmp label
跳转到9000:100地址处,BaseOfLoader=0x9000,OffsetOfLoader=0x100
ATT:
ljmp $BaseOfLoader, $OffsetOfLoader
NASM:
jmp BaseOfLoader:OffsetOfLoader
ATT:
向前跳转到标号1处,f表示forward
jmp 1f
1:
xxxxxxx
向后跳转到标号2处,b表示back
2:
xxxxxxx
jmp 2b
NASM:
没有前后之分
跳转到标号.0处
.0:
xxxxxxx
jmp .0
ATT:
把SEG32_MODE32_CS装入CS,0x12345装入EIP,并跳转到SEG32_MODE32_CS:$0x12345
ljmpl $SEG32_MODE32_CS, $0x12345
NASM:
把SelectorCode32装入CS,把0装入EIP,并跳转到 SelectorCode32:0 处
jmp dword SelectorCode32:0
ATT:
.macro name arg1, arg2, arg3...
宏定义内容
.endm
举例:段描述符
# 代码段/数据段描述符
# usage: Descriptor Base, Limit, Attr
# Base: .long 4字节长度
# Limit: .long 4字节长度
# Attr: .short 2字节长度
.macro Descriptor Base=0x0, Limit=0xffffffff, Attr
.short \Limit & 0xffff
.short \Base & 0xffff
.byte (\Base >> 16) & 0xff
.short ((\Limit >> 8) & 0xf00) | (\Attr & 0x0f0ff)
.byte (\Base >> 24) & 0xff
.endm
宏的参数可以设置默认值
宏的内部引用参数时,使用'\'表示引用的参数
NASM:
%macro name nargs
宏定义内容
%endmacro
举例:段描述符
; 描述符
; usage: Descriptor Base, Limit, Attr
; Base: dd
; Limit: dd (low 20 bits available)
; Attr: dw (lower 4 bits of higher byte are always 0)
%macro Descriptor 3
dw %2 & 0FFFFh ; 段界限1
dw %1 & 0FFFFh ; 段基址1
db (%1 >> 16) & 0FFh ; 段基址2
dw ((%2 >> 8) & 0F00h) | (%3 & 0F0FFh) ; 属性1 + 段界限2 + 属性2
db (%1 >> 24) & 0FFh ; 段基址3
%endmacro ; 共 8 字节
宏的内部引用参数时,使用%n表示引用的参数
查看cpu信息
/* cpuid.c */
/* gcc -o cpuid cpuid.c */
#include
#include
static inline void cpuid(unsigned int index,
unsigned int *eax,
unsigned int *ebx,
unsigned int *ecx,
unsigned int *edx)
{
asm("cpuid"
: "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx)
: "0" (index));
}
void main(void)
{
unsigned int eax, ebx, ecx, edx;
cpuid(0, &eax, &ebx, &ecx, &edx);
printf("eax = %x\n", eax);
printf("ebx = %x\n", ebx);
printf("ecx = %x\n", ecx);
printf("edx = %x\n", edx);
}
运行结果
结果分析参考intel手册volume 2,chapter 3,3.2章节中对CPUID指令的输出介绍
asm [ volatile ] (
assembler template
[ : output operands ] /* optional */
[ : input operands ] /* optional */
[ : list of clobbered registers ] /* optional */
);
"=a" (output)
output operand
的应遵守的约束(constraint
),output为存放指令结果的变量,通常是个C语言变量。"="是输出操作特有约束,表示操作数是只写的(write-only),表达式的意思是先将命令执行结果输入到eax寄存器中,然后再由寄存器eax更新位于内存中的output"constraint" (input)
constraint
指定input operand
的应遵守的约束(constraint
),input为存放输入的变量,通常是个C语言变量。比如:asm("cpuid" : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) : "0" (index));