The Long Walk1.4 一段旅途的结束

During the golden week, I absolutely have finished the first part of my journey, I have studied half of the book ‘Intel 64bits assembly language’ and The first 5 chapters of ‘Operating system concept’. And I have made the note about it, I will upload it here

**

Assembly Language 数据传送、寻址和算数运算

**
操作数类型:立即操作数(imm8/16/32)、寄存器操作数(reg/sreg)和内存操作数(mem)
直接内存操作数:
.data
var1 BYTE 10h
;指令使用内存操作数时实际上使用的是操作数的地址
mov al, val1
;被翻译的机械指令为 A0 00010400,第一个是操作码,第二个是var1十六进制的32位地址值

mov指令的两个操作数不能均为内存操作数,目的不能是cs、eip和ip
由于有符号和无符号整数的区别,使用movzx和movsx指令
movzx将源操作数内容复制到目前操作数中,并将该值扩展为16位或32位。仅适用于无符号整数,使用movzx就能将8位寄存器移入16位寄存器
movsx…,并将该符号扩展至16或32位

LAHF和SAHF指令
LAHF指令将EFLAGS寄存器的低字节复制进入AH寄存器:符号、零、辅助进位、奇偶、进位标志
SAHF用于恢复EFLAGS寄存器中的内容

XCHG指令交换两个操作数的内容,使用方式于mov类似,但不接受立即数操作

NEG指令将数字转换为相应的补码,EFLAGS内容将会被影响(将目的操作数的所有数据位取反后加1)
p81

零标志、进位标志和辅助进位标志
奇偶标志在运算结果的最低有效字节中为1的位数是偶数时置位,如
mov al, 10001100b
add al, 00000010b ;Al = 10001110, PF = 1
sub al, 10000000b ;Al = 00001110, PF = 0
符号标志: 有符号运算的结果为负时,符号标志置位。
mov eax, 4
sub eax, 5 ;EAX = -1, SF = 1
溢出标志: 有符号运算结果上溢或下溢以至于目的操作数无法容纳,溢出标志置位
mov al -128
sub al, 1 ; OF = 1
两个情况说明了溢出:
两个正数相加产生负数
两个负数相见产生正数
CPU如何检测溢出:运算结果最高有效位向高位的进位值(CF)与到最高有效位的进位值异或的结果放到溢出标志中
1000000
11111110
01111110
(6位到7位无进位,7位有进位)
1 XOR 0 = 1, OF = 1 ;考虑符号位的情况,符号位是否应该在这种情况下改变与否,是检测溢出的核心

NEG指令,如果目的操作数无法正确存储,那执行NEG指令可能会产生无效结果:
mov al, -128
NEG al ;AL = 10000000b, OF = 1

ALIGN伪指令将变量的位置按字节、字、双字对齐
格式为 ALGIN 边界值
bval BYTE ? ;00404000
ALGIN 2
wval WORD ;00404002

PTR操作符用来重载操作数声明的默认尺寸。如将双字变量myDouble的低16位送入AX寄存器,可以这么写:
.data
myDouble DWORD 12345678h
.code
mov ax, myDouble ;错误
但可以这样写:
mov ax, word ptr myDouble
同时记住这种操作:
.data
array word 4567h, 1234h
mov eax, dword ptr array

扫描二维码关注公众号,回复: 8904412 查看本文章

Type操作符返回以字节计算的变量单个元素的大小
.data
var1 BYTE ?
var2 word ?
TYPE var1 ;==1

LENGTHOF 计算数组中元素的数目
SIZEOF 为LENGTHOF * TYPE

SIZEOF操作符 = TYPE操作符结果 * LENGTHOF操作符结果

LABEL伪指令允许插入一个标号并赋予其尺寸属性而不为奇分配实际的存储空间,通常是为数据段后定义的变量提供一个别名以及一个不同的尺寸属性
.data
val16 LABEL WORD
val32 DWORD 1234567h
.code
mov ax, val16 ;ax = 5678h
mov dx, [val16 + 2] ;dx = 1234h

变址操作数(Indexed operand)
把常量和寄存器相加得到一个有效地址。格式:
arrayB[esi] == [arrayB + esi]
arrayD[ebx] == [arrayD + ebx]

指针 包含其他变量地址的变量成为指针或指针变量,包括两种类型,NEAR和FAR指针
arrayB BYTE 10h, 20h, 30h
arrayW WORD 1000h, 2000h, 3000h
ptrB DWORD arrayB
ptrW DWORD arrayW

使用TYPEDEF允许创建用户自定义的类型,定义一个指向字节的指针PBYTE
PBYTE TYPEDEF PTR BYTE
详细查阅95页

JMP和LOOP指令
JMP 目标地址 ;格式
目标标号的偏移地址被装入指令指针中
LOOP 目的地址 ;以ECX为递减寄存器
循环的嵌套:
.data
count DWORD ?
.code
mov ecx, 100
L1:
mov count, ecx
mov ecx, 20
L2:
.
.
LOOP L2
mov ecx, count
LOOP L1

Assembly Language 与外部库链接

链接库(link library)是一个文件,其中包括很多已经编译成机器码的过程。库可以由一个或多个源代码文件组成,这些文件被汇编成目标文件,然后这些目标文件被插入到一个特定格式的文件——库中。
WriteString PROTO
call WriteString
汇编器编译程序时,会为Call指令的目的地址留出空白,随后该空白由链接器填充为实际的目标地址。链接器在链接库中查找WriteString这个名字,并把库中的机器指令复制到程序的可执行文件中,然后WriteString在可执行文件中的实际地址插入到CALL指令为目的地址留出的空白处

USES操作符 与PROC伪指令配套使用的USES操作符允许列出被过程修改的所有寄存器。指示编译器做两件事:首先,在过程开始处生成push指令在堆栈上上保存寄存器,其次,在过程结束处生成POP指令回复寄存器的值。USES操作符应该紧跟PROC伪指令,其后跟由空格和制表符分隔的寄存器列表:

ArraySum PROC USES esi ecx

ArraySum PROC
push esi
push ecx

pop ecx
pop esi

大量外部库内容请详细查阅本章

Assembly Language 条件处理

AND指令 用于清除选定的位并保留其他位 总是清除溢出标志和进位标志
OR指令执行“或”操作
XOR执行“异或”操作:XOR指令的一个特性是,某个操作数与同样的操作数执行了两次异或运算后,其值保持不变。因此这成为了一种对称加密的理想工具。
奇偶标志位:XOR总是清除溢出标志和进位标志,根据操作数的值修改符号标志、零标志和奇偶标志
奇偶标志位表明了位操作或算数操作的结果的最低字节包含为1的数据位的个数是奇数还是偶数
16位的奇偶值:
mov ax, 64C1h
xor ah, al
16位数据其实是两个8位数据,如果将两个八位数据中同为1的交集去掉,剩下的位的奇偶性与原16位数据相同

NOT指令取得反码
TEST指令在每对操作数的对应数据之间执行隐含的“与”操作
CMP指令执行隐含的减法操作 CMP 目的操作数 源操作数 ;目的-源

设置和清除单个CUP状态标志
test al, 0 ;设置零标志
and al, 0 ;设置零标志
or al, 1 ;清除零标志
设置符号标志:
or al, 0 ;设置符号标志
and al, 7FH ;清除符号标志
STC ;设置进位标志
CLC ;清除进位标志

条件跳转
条件跳转指令
jc 如果进位则跳转
jnc 如果无进位则跳转
jz 如果为零则跳转
jnz 如果非零则跳转

使用CMP指令
cmp ax, 5
je L1
如果ax不等于5,CMP就会清除零标志,执行JE指令就不会发生跳转
mov ax, 5
cmp ax, 6

jl L1 ;小于则跳转

mov ax, 5
cmp ax, 4
jg L1 ;大于则跳转

条件跳转的应用
字符串加密,XOR的可逆
把用户输入的消息中的所有字符都同另一个字符串进行XOR操作,可以将它转换为不可识别的字符串P153有趣的加密程序

位测试指令
BT指令选择第一个操作数的位n并把它复制到进位标志去/BTC指令,将位n取反后放入进位标志/BTS指令,将位n放入进位标志后取反
BT bitbase, n ;第一个操作数称为位基
等同于:
mov ax, semaphore
shr ax, 8

LOOPZ和LOOPE指令
允许在零标志置位并且ECX中的无符号值大于0时循环,目标标号距离LOOPZ后下一条指令应该在-127~128字节范围里:
LOOPZ 目的地址
执行逻辑:ECX = ECX - 1 ;如果ecx>0并且zf=1,跳转

LOOPNZ和LOOPNE指令
LOOPNZ 目的地址
执行逻辑:ECX = ECX - 1 ;如果ecx>0并且zf=0,跳转

And I will upload the rest of my note in following blogs

发布了47 篇原创文章 · 获赞 10 · 访问量 1726

猜你喜欢

转载自blog.csdn.net/Antonio_Salieri/article/details/102297475