use16
: 16位寻址segment
: 是段定义语法
assume cs:code, ds:data
告诉编译器,某个变量段地址为data:
时要替换为ds:
.
其中 assume
为伪指令
-
.386
为伪指令,表示使用哪个指令集。 -
命令行参数:
C/C++ 中 main 函数的 argc 与 argv.
执行:
g++ .\main.cpp -o main
.\main.exe 123 456
输出文件位置, 123, 456.
#include<iostream>
#include<windows.h>
using namespace std;
const int N=2e5+10;
int main(int argc,char *argv[]) {
if(argc==3){
printf("%s %s %s",argv[0],argv[1],argv[2]);
}
system("pause");
return 0;
}
汇编中psp:[80h]处存放了命令行参数的长度,psp:[81h]开始存放命令行参数。注意这里psp不是寄存器,前面写法是为了简便,想要访问psp需要用未赋初值的ds/es寄存器。
-
ss:sp ss:sp指向堆栈顶端。 每次push操作, sp=sp-2, 按小端规则存入变量。
-
es 初始指向psp,需要赋值后使用。
-
只有
bx,bp,si,di
可以放在[]
中。 -
cli/sti:IF=0/1 禁止/启用硬件中断,Windows/linux中是特权指令,用户程序没有权限执行这两条指令,只有操作系统可以执行。(编写驱动程序)
-
int8h:时钟中断,用于分时,运行多进程程序
-
int9h:键盘中断,读取键盘按下对应编码
-
TF:Trap Flag,陷阱标志,TF=1,CPU进入单步模式:执行完一条指令,插入一条int1h并执行,int1h称为单步中断,按下键盘后执行下一步。
- int1h可以用来反调试:调试器与程序抢夺int1h的绑定关系,程序抢到int1h调试器就不能运行,调试器抢到int1h程序就不能运行(可以在自己的int1h对指令机器码加减某个数做加密/解密)。
- 显卡控制:段地址B800h,通过更改里面内容,显示不同的字母/背景颜色
- 用方波发生器唱歌
- 32位寻址:eax,ecx,edx,esp,ebx,ebp,esi,edi都可以放在[]中。
-
[寄存器+寄存器]对寄存器组合无限制(16位只能b_+_i而不能di+si,bx+bp);
还有[eax+ebx*n+c],n=1,2,4,8;c常数
当[]中有bp,默认段地址为ss 18. 发生Divide overflow时,cpu会在当前指令上方插入一条int00h并执行 19. int00h的函数地址保存在dword ptr 0:[0]中 20. softice:
21. 22. cbw,cwd:字节到字扩展,字到双字扩展 23. movzx,movsx:zero expansion,sign expansion 24. imul:ldr //调试某个程序 F6/ec entercode//进入代码窗 d 0:0 跳转到地址0:[0] u 684:8 观察code段中的指令 F2/BPX 断点 x execute 执行,相当于td的run,全速执行 F8 单步执行 F5 用户屏幕 ec enter code-window进入代码窗 ctrl+d 挂起softice bpmb //Break Point on Memory Byte //softice支持4个硬件断点,他会把断点地址写入调试寄存器dr0,dr1,dr2,dr3,再把断点类型信息(R,W,RW,X)写入dr7 bpmb cs:104 x //在cs:104处设一个执行硬件断点 bpmb ds:200 w (C=01)//在ds:200处被改写(1次)时断住 bpmb ds:200 r//在ds:200处被读取时断住 R32 //观察32位寄存器 . //定位当前指令cs:[ip]
25. xlat:(translate) 查表指令 26. repe cmpsb:如果相等,则继续比较 27. cmpsb会停在不等的位置的后一位,则需要-1获得不等的两个元素 28. 判断全等:如果zf=1,则最后一次比较也是相等的,则全等imul eax,ebx ;eax*=ebx imul eax,ebx,3;eax=ebx*3
29. scasb 扫描repe cmpsb je equal ;如果ZF=1,则全等 repne cmpsb jne not_equal
可用来计算字符串长度/跳过前导重复字符cmp al, es:[di]
-
stosb 赋值store
相当于memsetmov es:[di], al
-
lodsb 加载load
lodsb 加rep没有意义mov al, ds:[si]
-
几个特殊位置
0000:7C00 第一个扇区
B800
psp
0000:0000
- tasm /m2 jmp 扫描两次来解决不知道跳转是短跳还是近跳导致的nop的出现 然后使用tlink 来link
-
byte ptr ; 1字节 word ptr ; 2字节 dword ptr; 4字节(32位整数或float类型小数) fword ptr; 6字节(4字节偏移地址+2字节段地址) qword ptr; 8字节(64位整数或double类型小数) tbyte ptr; 10字节(long double类型的80位小数) short 用来修饰一个短的标号 near ptr 用来修饰一个近的标号 far ptr 用来修饰一个远的标号
-
call far ptr + retf 远跳调用函数
-
__asm int 3在C语言中加入软件断点
-
ret n , n是参数,表示将栈退回n个byte
-
pragma comment(linker, '\SECTION:.text.RWX') 让windows代码段(code段)可写,可以改动printf等函数
-
it's been a long day without you my friend and i'll tell you all about it when i see you again we've come a long way from where we began oh i'll tell you all abnout it when i see you again. when i see you again. damn who knew all the place we flew good things we been through that i'll be standing right there talking to you bout another path i know we love to hit the road and laugh
-
这段程序无法正确显示a[1],因为a[1]是动态变量,子程序结束后栈空间退回,动态变量死亡。 所以使用static.
#include<stdio.h> int *f(int i){ int a[3]={10,20,30}; return *a[i]; } int main(){ int *p; p=f(1); printf("%d\n",*p); return 0; }
#include<stdio.h> int *f(int i){ static int a[3]={10,20,30}; return *a[i]; } int main(){ int *p; p=f(1); printf("%d\n",*p); return 0; }
-
事实上不被覆盖就可以正确显示,但是有
[Warning] address of local variable 'a' returned [-Wreturn-local-addr]
-
gcc内嵌asm:
#include<stdio.h> int main(){ int input=1, output=0,temp=-1; printf("%d\n",output); printf("%d\n",temp); __asm__ __volatile__ ("movl $0, %%eax; movl %%eax, %1; movl %2, %%eax; movl %%eax, %0; " :"=m"(output),"=m"(temp) /* output */ :"r"(input) /* input */ :"eax"); /* 描述符 */ printf("%d\n",output); printf("%d\n",temp); return 0; }
-
__declspec(naked)?
- ip和fl时无法正常赋值的寄存器,使用ret,call,pushf,popf等进行更改/取出
- gbt 全局描述符
- lgbt 把gbt中的内容加载到gbtr中(48位向量)
- sgbt 把gbtr中内容复制到gbt中
- 指令+中断汇总
int 21h(ah=01h,02h,09h,0ah)
int 8h;时钟中断
int 0h;除法溢出
int 1h;单步执行
int 3h;软件断点
int 9h;键盘按下/释放
int 10h;图形模式
db,dw,dd,df,dq,dt
add
sub
mul
imul
div
idiv
xchg
xlat
pop
push
popf
pushf
lgbt
sgbt;gbt,寄存器gbtr
mov
movsb
cmpsb
scasb
stosb
lodsb
rep
call
ret
call far ptr
retf
int
iret
daa; 判断AF=1,AL的低4位向高4位进位/借位,或(AL & 0Fh)>9,此时AL=AL+6
cli
sti
cld
sti
stc
clc
movzx
movsx
cbw;al->ax
cwd;ax->dx:ax
cdq;eax->edx:eax
sbb/adc
dec/inc
neg;求相反数
fadd/fsub/fmul/fdiv
fld ;入栈加载
fstp ;出栈保存
sal
sar
jcxz
- 以读取键盘为例, 以下为从高层到低层的编程方式排序:
dos 高 mov ah, 1; int 21h 功能弱,但编程简单 bios 中 mov ah, 0; int 16h in/out 低 in al, 60h; 功能强, 但编程麻烦
- push word ptr ds:[bx+2] 允许push后加内存
- 16位汇编中,远指针是指16位段地址:16位偏移地址; 32位汇编中,远指针是指16位段地址:32位偏移地址。 48位的远指针在汇编语言中有一个类型修饰词: fword ptr 近指针(near pointer):偏移地址就是近指针 16位汇编中,近指针是指16位的偏移地址; 32位汇编中,近指针是指32位的偏移地址;
- mul/imul第二种用法
mul eax, ebx; eax = eax * ebx imul eax, ebx, 3; eax = ebx * 3