Appearance
x86汇编学习
loop指令
loop指令的作用是将cx寄存器减1,并判断是否为0,如果不为0则跳转到指定地址,用于循环。
asm
; 例:计算2的5次方
assume cs:code
code segment
start:
mov cx,5 ; 循环次数
mov ax,1 ; 乘数
mov bx,2 ; 结果
loop1:
mul bx ; ax = ax * bx
loop loop1 ; cx--,如果不为0则跳转到loop1
; 循环结束,ax中存放2的5次方
; 结果为32,ax=20h
code ends
end start
代码复制
适用情况: 将当前段的代码转移到另一个段中执行。
asm
assume cs:code
code segment
s:
mov ax,bx ; 要被转移的代码,长度为2字节
mov si,offset s ; 代码段的偏移地址
mov di,offset s0 ; 要转移到的段的偏移地址
mov dx,cs:[si]
mov cs:[di],dx
s0:
nop
nop
code ends
end s
jmp指令
asm
s:
nop
; 可以直接在debug中编写
jmp 100
jmp 0760h:100
jmp ax
; 无法直接在debug中编写
jmp short s ; 短跳转,跳转到s段的偏移地址,ip被修改
jmp short执行的是段内转移,对IP修改范围为-128~127,并非直接跳转到相应的地址,而是通过偏移量先查询到相应偏移地址再实现跳转。
asm
jmp near ptr s ; 段内近转移,会报错
jmp far ptr s ; 段间远转移,不会报错
db 256 dup(0)
s:
nop
jmp near ptr范围和jmp short相同,只记录段内偏移地址,jmp far ptr记录段内偏移地址和段地址。
转移地址在内存中有两种格式:
- jmp word ptr 内存单元地址(段内转移)
asm
mov ax,012H
mov ds:[0],ax
jmp word ptr ds:[0] ; IP=0123H
; 或者
mov ax,0123H
mov [bx],ax
jmp word ptr [bx] ; IP=0123H
- jmp dword ptr 内存单元地址(段间转移)
asm
mov ax,0123H
mov ds:[0],ax ; 偏移地址
mov word ptr ds:[2],0 ; 段地址
jmp dword ptr ds:[0] ; CS=0,IP=0123H
数组
- 数组定义
asm
assume cs:code,ds:data
; 可以用变量名命名数组
; 注意不能带冒号,带冒号则视为代码
data segment
arr dw 12,34
arr2 db 'hello'
data ends
; 可以用变量名访问数组,type查询数组类型
code segment
start:
mov ax,type arr ; ax=0002h
mov ax,type arr2 ; ax=0001h
code ends
end start
- 数组访问
类似C语言。
asm
assume cs:code
code segment
arr dw 12,34,56,78h
arr2 db 'hello'
start:
mov ax,arr[0] ; ax = 01H
; 或者
mov si, offset arr
mov ax, cs:[si] ; ax = 01H
; 强制类型转换
mov ax,word ptr arr2[0] ; byte转化为word
code ends
end start
如果数据存储在数据段中的情况:
asm
assume cs:code,ds:data
data segment
arr dw 12,34,56,78h
arr2 db 'hello'
data ends
code segment
start:
mov ax,data ; 先将数据段地址存入ax中
mov ds,ax ; 再将数据段地址赋值给ds
mov ax,arr[0] ; ax = 01H
code ends
end start
- 数组写入
asm
assume cs:codev
code segment
arr db 12,34,56,78h
start:
mov al,arr[3]
mov arr[0],al
mov al,arr[0] ; al = 78h
code ends
end start
第一个程序: 输出hello world
asm
assume cs:code,ds:data
data segment
msg db 'hello world',10,'$' ; 10为换行符,字符串以$结束
data ends
code segment
start:
mov ax,data ; 先将数据段地址存入ax中
mov ds,ax ; 再将数据段地址赋值给ds
mov dx, offset msg ; dx指向字符串的首地址
mov ah,9
int 21h ; 调用DOS的9号功能,输出字符串
; 退出程序
mov ah, 4Ch
int 21h ; 调用DOS的4Ch功能,退出程序
code ends
end start