|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
在整理之前学习的一些资料,这是暑假时候学习汇编语言的一些收获,和大家相互学习,本人也属于菜鸟初学者,看的是王爽的那本汇编语言,主要是前十一章的(因为想着是学习逆向,后边的就没看了)。
先是一些汇编编程的细节:
-1 在编写汇编程序时要注意十六进制数不能以字母开头,如果原始数是以字母开头,要在前面加上0,否则在编译的时候就不能被识别出 来,如果不是以字母开头则不作改变,并以H/h结尾表示该数是十六进制数。
-2 在初始化阶段,在定义一个段的时候,可以同一个段里根据需要定义多个不同的段,段的名字根据需要也可以定义为易读的名字,在编译的时候段寄存器和段的名字是由编译器识别,并将二者联系在一起
-3 执行“jmp short 标号”等指令时,进行的是短转移,即段内转移,cup并不知道标号的地址,也就是说cpu并不清楚要跳到哪里,cpu根据的是指令在编译的时候由编译器计算得到的需要跳转的位移大小,(IP = IP + 8位位移,8位位移 = 标号的地址 - jmp指令后面第一个字节的地址,范围是-128~ 127),超过范围会报错。cup所知道的就是这个位移,它并不管目的地址在哪里,只需要知道位移即可,位移的计算交由编译器完成,所以说这时cpu并不需要知道转移的目的地址。
-4 内存地址中B8000h-B8fffh共32k的空间,为80x25彩色字符模式的显示缓冲区,向这个地址空间写入数据,写入的内容将立即显示在显示器上。
-5 PC机主板的ROM写有一个生产日期,在内存fff00h-fffffh的某几个单元中,这类值是修改不了的。
-6 在执行“call 标号”指令的过程,首先明白它实现的是段内转移,首先是push ip,这里的ip是指“call 标号”指令后面第一个字节处的地址,并不是该指令对应的机器码中e8后面两个字节的内容,执行完push ip后,ip = ip + 16位位移,执行这个动作根jmp指令原理相同,16位位移 = 标号处的地址 - “call 标号”指令后面第一个字节处的地址。可见,在这么些跳转指令中,这些指令后面第一个字节处的地址起着关键性作用。“call far ptr 标号”进行的是段间转移,过程跟前面差不多。都是用栈来保存当前的ip(cs)。
-7 当执行完一条指令后,ip = ip + 该指令所占字节长度,这个动作是无条件执行的。
-8 执行乘法指令mul的时候,如果是八位以内,结果存放在AX(255*255 = 65025<65535)中,如果是16位以内,以80x86cpu为例,结果的低16位存放在AX,高16位存放在DX中,空余位置自动补零。
-9 在flag寄存器中记录了每条指令执行后各个状态位的情况,要注意的是有些指令不影响这些状态位,比如loop指令,inc指令;另外cmp指令执行后看的是flag寄存器中的情况,并不影响参加运算的寄存器的数据。
上面说的好像不痛不痒,就是在学习的时候遇到的觉得重要所以就记下了,下面是几个例子,可以帮助理解。
00:汇编中循环的原理
;在进行调试的时候,第一次用P只是进行了首轮循环,第二次再下P才会将剩下的所有循环进行完,所以这种情况只用一次P是不够的,P的使用得要结合具体情况
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
db 'ibm.............'
db 'dec.............'
db 'dos.............'
db 'vax.............'
datasg ends
stacksg segment
dw 0,0,0,0,0,0,0,0;定义一个stack,用来保存cx
stacksg ends
codesg segment
star :
mov ax,datasg
mov ds,ax
mov bx,0
mov cx,4
s:push cx ;将外层循环的cx保存在stack
mov si,0
mov cx,3 ;cx作为内层循环的次数
d: mov al,[bx+si]
and al,11011111b
mov [bx+si],al
inc si
loop d
add bx,16
pop cx ;将stack中的值还原给cx
loop s
mov ax,4c00h
int 21h
codesg ends
end star
01:初识汇编结构体
assume cs:code,ds:data,es:table
data segment
db '1975','1976','1977','1978','1979','1980','1981','1982','1983'
db '1984','1985','1986','1987','1988','1989','1990','1991','1992'
db '1993','1994','1995'
dd 16,22,382,1356,2390,8000,16000,24486,50065,97479,140417,197514
dd 345980,590827,803530,1183000,1843000,2759000,3753000,4649000,5937000
dw 3,7,9,13,28,38,130,220,476,778,1001,1442,2258,2793,4037,5635,8226
dw 11452,14430,15257,17800
data ends
table segment
db 21 dup ('year summ ne ?? ')
table ends
code segment
start: mov ax,data
mov ds,ax
mov ax,table
mov es,ax
mov bx,0
mov si,0
mov di,0
mov cx,21
s: mov ax,[bx]
mov es:[si],ax
mov ax,[bx].2
mov es:[si].2,ax
mov ax,[bx].84
mov es:[si].5,ax
mov dx,[bx].86
mov es:[si].7,dx
div word ptr ds:[di].168
mov es:[si].13,ax
mov ax,[di].168
mov es:[si].10,ax
add di,2
add bx,4
add si,16
loop s
mov ax,4c00h
int 21h
code ends
end start
02深入理解jmp指令(段内转移)
assume cs:codesg
codesg segment
mov ax,4c00h
int 21h
start : mov ax,0
s: nop
nop
mov di,offset s
mov si,offset s2
mov ax,cs:[si]
mov cs:[di],ax
s0: jmp short s
s1: mov ax,0
int 21h
mov ax,0
s2: jmp short s1
nop
codesg ends
end start
code ends
03在显存中写入内容以彩色显示
assume cs:code
data segment
db 'welcome to masm!'
data ends
code segment
start: mov ax,data
mov ds,ax
mov ax,0b800h
mov es,ax
mov bx,0720h ;关键点1 : 设置中间行中间列的首地址 160*11+64
mov si,0
mov cx,16
s: mov ax,[si] ;关键点2 : si控制字符的变化
mov ah,2h
mov es:[bx],ax ;设置绿色字体
mov ah,24h
mov es:[bx].0a0h,ax ;关键点3 :设置绿底红色,0a0h相当于十进制的160,即跳到下一行的相同位置处
mov ah,71h
mov es:[bx].0a0h.0a0h,ax ;设置白底蓝色,灵活的运用ah进行字符颜色属性的修改
inc si ;指向下一字符
add bx,2 ;指向下一显存单元
loop s
mov ax,4c00h
int 21h
code ends
end start
04大小写转换
assume cs:code
code segment
data segment
db 'word',0
db 'unix',0
db 'name',0
db 'byte',0
data ends
start: mov ax,data
mov ds,ax
mov bx,0
mov cx,4
s: mov si,bx
push cx
call fun
pop cx
add bx,5
loop s
fun : mov cl,ds:[si]
mov ch,0
and [si],11011
;有个细节要注意,[si]是byte数据,所以11011111应该也是八位,空位根据情况补齐,不然8位与7位无法运算
jcxz s1
inc si
jmp short fun
s1: ret
code ends
end start
最后是几个反汇编中常遇到的条件转移指令:
--------------------------------------------------------------------------------
指令 含义 相关标志位的状态
--------------------------------------------------------------------------------
je 等于则跳转 ZF = 1
jen 不等于则跳转 ZF = 0
jb 低于则跳转 CF = 1
jnb 不低于则跳转 CF = 0
ja 高于则跳转 CF = 0 , ZF = 0
jna 不高于则跳转 CF = 0 或 ZF = 0
-------------------------------------------------------------------------------- |
|