汇编(五)

跳转指令

offset 获取标号的偏移地址

jump 无条件跳转

  • jmp short 标号 范围为 -128 ~ 127 本质上跳转的是偏移地址,也就是改ip不改cs
1
2
3
4
5
6
7
8
9
10
11
12
13
assume cs:codesg

codesg segment
start: mov ax,0
jmp short s
add ax,1
s: inc ax

mov ax,4c00h
int 21h

codesg ends
end start
  • jmp near ptr 标号 范围 -32769 ~ 32767

  • jmp far ptr 标号 段间跳转,本质是直接修改cs和ip的值

  • jmp 16位寄存器 直接将ip设置为寄存器中的内容

  • jmp word ptr 内存单元地址 从内存单元地址处开始存放着一个字,是转移的目的偏移地址

  • jmp dword ptr 内存单元地址 段间跳转 高地址对应cs,低地址对应ip

jcxz 有条件跳转{短转移}

  • cx==0 时 进行跳转;相当于 if(cx == 0) jmp short 标号

loop 循环跳转 {短转移}

  • cx != 0 跳转

call和ret指令

ret 指令,从栈中取出数据修改ip的值

相当于

1
pop IP

retf 指令,从栈中先取出一个值修改ip,再取出一个值修改cs

相当于

1
2
pop IP
pop CS

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
assume cs:codesg,ss:stack

stack segment
db 16 dup (0)
stack ends

codesg segment
mov ax,4c00h
int 21h
start:
mov ax,stack
mov ss,ax
mov sp,16
mov ax,0
push cs
push ax

retf
codesg ends
end start

call 指令

将当前的ip或者cs和ip压入栈中并跳转

  • call 标号 段内跳转
  • call far ptr 标号 段间跳转
  • call 16位寄存器
  • call word ptr 内存单元地址
  • call dword ptr 内存单元地址
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    assume cs:codesg

    codesg segment
    start:
    mov ax,1
    mov cx,3
    call s
    mov bx,ax ;bx 最后值为8
    mov ax,4c00h
    int 21h
    s: add ax,ax
    loop s
    ret
    codesg ends
    end start
  • 示例1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    assume cs:codesg,ds:data,ss:stack

    data segment
    db 'word',0
    db 'unix',0
    db 'wind',0
    db 'good',0
    data ends

    stack segment
    db 8 dup (0)
    stack ends

    codesg segment
    start:
    mov ax,data
    mov ds,ax

    mov ax,stack
    mov ss,ax
    mov sp,9

    mov bx,0

    mov cx,4
    s: mov si,bx
    push cx
    call capital
    pop cx ;不能放到ok后面ret前面,因给call和ret也会使用栈存储数据
    add bx,5
    loop s

    mov ax,4c00h
    int 21h
    capital:mov cl,[si]
    mov ch,0
    jcxz ok
    and byte ptr [si],11011111b
    inc si
    jmp short capital
    ok: ret

    codesg ends
    end start

标志寄存器

  • ZF—第六位 结果是否为0 1表示为0 0表示不为0
  • PF—第二位 奇偶标记位【结果的二进制表示中有奇数个还是偶数个1】 1偶数 0奇数
  • SF—第七位 符号标志位 1为负数 0为正数
  • CF—第零位 最高位发生了进位/借位标志位(对于无符号数运算) 1产生进位 0没有产生

    adc 指令 sbb 指令

  • OF— 溢出标记位(有符号运算)
  • DF—第十位 方向标识位 1表示si/di 递减 0表示递增

    movsb movsw cld std

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    assume cs:codesg

    data segment
    db 'Welcome to masm!'
    db 16 dup (0)
    data ends

    codesg segment
    start: mov ax,data
    mov ds,ax
    mov si,0
    mov es,ax
    mov di,16
    mov cx,16 ;rep 循环16次

    cld ;设置cf=0,正向传递
    rep movsb

    mov ax,4c00h
    int 21h

    codesg ends
    end start

cmp 指令

  • cmp ax,ax 不会把结果保存在ax中,结果只会影响标志寄存器中的值
  • cmp ax,bx 结果分析 (ax) - (bx), ax,bx无符号数

    (ax) == (bx):ZF = 1

    (ax) != (bx):ZF = 0

    (ax) < (bx):CF = 1

    (ax) <= (bx):CF = 1 || ZF = 1

    (ax) > (bx):CF = 0 && ZF = 0

    (ax) >= (bx):CF = 0

无符号比较结果的跳转指令

je jne jb jnb ja jna

速记

e:equal b:below a:above

pushf 和 popf 将标志寄存器的值进行入栈和出栈处理

中断处理

修改0中断信息处理程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
assume cs:codesg

codesg segment
start:
mov ax,cs
mov ds,ax
mov si,offset do0 ;设置ds:si指向源地址
mov ax,0
mov es,ax
mov di,200h ;设置es:di指向目的地址
mov cx,offset do0end - offset do0 ;设置cx为传输长度
cld ;设置传输方向为正
rep movsb

mov ax,0 ;设置中断向量表
mov es,ax
mov word ptr es:[0*4],200h
mov word ptr es:[0*4+2],0

mov ax,4c00h
int 21h

do0: jmp short do0start
db "Welcome to Fishc.com!"

do0start:
mov ax,cs
mov ds,ax
mov si,202h ;设置ds:si指向字符串

mov ax,0b800h
mov es,ax
mov di,12*160+36*2 ;设置es:di指向显存空间的中间位置

mov cx,21 ;设置cx为字符串长度
s: mov al,[si]
mov es:[di],al
inc si
add di,1
mov al,02h ;设置颜色
mov es:[di],al
add di,1
loop s

mov ax,4c00h
int 21h
do0end: nop

codesg ends
end start

int 指令,主动调用指定类型中断

端口

汇编中的端口和网络编程中端口区别

不是一个概念。你说的那个PC系统中,CPU最多可以定位64K端口中的“端口”是IO端口,这个是X86 CPU中的一个概念,是为了使CPU能够访问外部设备中的寄存器而存在的指令,是CPU指令集的一部分。而后面的ftp http中的端口,纯粹是TCP/IP协议的东西,是纯软件层的东西

指令 in out