Skip to content

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记录段内偏移地址和段地址。

  转移地址在内存中有两种格式:

  1. 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
  1. 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

数组

  1. 数组定义
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
  1. 数组访问

  类似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
  1. 数组写入
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