汇编(assembly)
前置知识
CPU中需要将数据或指令存入寄存器中才能对其进行操作。
地址个人理解(
数据都是存在内存中某一特定地址中, CPU访问内存时可以通过地址来获取某块内存上的数据
用来存放地址的变量, 我们称为指针, 不论何种数据类型(int, char, 结构体), 指向它所在地址的指针大小都为4字节, 所以下面的程序里弹栈操作我们会使其ESP寄存器(存放栈顶指针)加4(Intel系统中栈是向下生长的, 改变栈顶位置使其+4也就是实现一个弹栈操作)
但是弹栈时指针移动的长度是看使用的寄存器类型
EAX为32位寄存器, 其中数据的大小刚好是4字节, 所以每次移动栈顶指针都要使其+4
AX为EAX的低16位的 “ 子寄存器 ”
AL为EAX(或说AX)低8位的 “ 子寄存器 ”
AH为AX高八位的“ 子寄存器 ”
汇编关键字
赋值
LEA (load effective address)
lea eax, a 是将a的地址复制到寄存器eax
MOV (move)
mov eax, a 是将a的值赋值给寄存器eax
ADD 加法运算
add eax, a 是将eax中的值加上a
SUB 减法运算
sub eax, a 是将eax中的值减去a
PUSH 入栈
push esp 是将eap的地址入栈(先让堆栈指针加一, 再压栈)
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
简单比较大小汇编程序解读
int main()
{
char message1[] = "Enter a first number";
char message2[] = "\bGive me a second number: ";
char message3[] = "\nThe numbers are equal!\n";
char message4[] = "\nSecond is larger!\n";
char message5[] = "\nFirst is larger";
char message6[] = "Type in any integer and press ENTER key to finish: ";
//scanf的读入整数的标志是%d
char format[] = "%d"; // format string for the scanf function
int first;
int second;
int end;
_asm{
;1输出message1
;这里注意一下,lea是传递地址,c语言中字符数组message1是数组名,也是字符串的首地址
;实测改成message1[0]也能正常执行,如果改成message1[4],则前4个字符不会输出
lea eax, message1
push eax
call printf
add esp, 4
;2读入first
lea eax, first
push eax
lea eax, format
push eax
call scanf
add esp, 8
;3输出message2
lea eax, message2
push eax
call printf
add esp, 4
;4读入second
lea eax, second
push eax
lea eax, format
push eax
call scanf
add esp, 8
;5判断是否相等, 不相等则jump到less判断first是否小于second
mov eax, first
sub eax, second
jnz less
;6两数相等,没有跳过,输出message3,jump到finish
equal:
lea eax, message3
push eax
call printf
add esp, 4
jmp finish
;7继承了5的状态,判断first是否小于second,不满足直接jump到large
less:
mov eax, first
sub eax, second
jl larger
;8first小于second,没有跳过,输出message5,并jump到finish
lea eax, message5
push eax
call printf
add esp, 4
jmp finish
;9输出message4,first大于second
larger:
lea eax, message4
push eax
call printf
add esp, 4
;10输出message6
finish:
lea eax, message6
push eax
call printf
add esp, 4
;11等待输入下一个数,防止程序执行完毕自动退出
lea eax, end
push eax
lea eax, format
push eax
call scanf
add esp, 8
}
return 0;
}