汇编2

又换了个人
玉涵大大

inc

等于“++”

1
inc ax

loop

循环
先看例子:计算212

1
2
3
4
5
6
7
8
9
10
11
12
13
assume cs:codee

codee segment

start:mov ax,2
mov cx,11
s: add ax,ax
loop s

mov ax,4c00h
int 21h
codee ends
end start

cx(计数寄存器)存放为循环次数,s为标识指令地址(即从哪里开始循环)
先向cx存次数,标号:执行循环语句,最后loop+标记
本质上是指令指针(IP)的移动,先(cx)减一,再判断其值若不为0则转至s标号处,为0则执行下一条

汇编中 ffffh 编译器认为是标识符,要写为 0ffffh

将ffff;0~ffff:b单元的数据的和,结果储存在dx中

先将8位数据赋值到另一个16位寄存器bx中,再作加:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
assume cs:code
code segment

start:
mov ax,0ffffh
mov ds,ax

mov dx,0
mov cx,12

s: mov al,ds:[bx]
mov ah,0
add dx,ax
inc bx
loop s

mov ax,4c00h
int 21h
code ends
end start

段的应用

下两例:不将数据段栈段和代码段分开
技术算以下8个数据的和,结果放在ax中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
assume cs:code
code segment
dw 0001h,0002h,0003h,0010h,0020h,0030h,0100h,0200h;写单位数据

start: ;指定开始执行正确代码
mov bx,0
mov ax,0

mov cx,8
s:add ax,cs:[bx];代码段的偏移地址为0、1、2、3的东西即目标数据
add bx,2
loop s

mov ax,4c00h
int 21h
code ends
end start

栈段
倒置数据

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
assume cs:code
code segment
dw 0001h,0002h,0003h,0004h,0005h,0006h,0007h,0008h;写单位数据
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;sp指向的最后一个零

start:
mov ax,cs
mov ss,ax;指令段-》栈段
mov sp,30h;48即(8+16)*2最后一个零

mov bx,0
mov cx,8
s:push cs:[bx];目标数据入栈
add bx,2
loop s

mov bx,0
mov cx,8
z:pop cx:[bx]
add bx,2
loop z

mov ax,4c00h
int 21h
code ends
end start


这两段代码认真debug看一下每一步


当然一般是分开的:

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
assume cs:codesg,ds:datasg,ss:stacksg
datasg segment
dw 0001h,0002h,0003h,0004h,0005h,0006h,0007h,0008h;写单位数据
datasg ends

stacksg segment
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;sp指向的最后一个零
stacksg ends

codesg segment

start:
mov ax,stacksg;不能直接写mov ss,stacksg
mov ss,ax;

mov sp,20h;48即(8+16)*2最后一个零

mov ax,datasg
mov ds,ax

mov bx,0
mov cx,8
s:push [bx];即ds:[bx]代替了cs:[bx]
add bx,2
loop s

mov bx,0
mov cx,8
z:pop [bx]
add bx,2
loop z

mov ax,4c00h
int 21h
codesg ends
end start

入栈
出栈

其它一些

debug中数据查看是每位反向的
debug默认输入16进制,编译时默认10进制

  • and
    常用
    1
    and al,10111111b
    对指定位置0
  • or
    常用
    1
    or al,10111111b
    对指定位置1
  • xor(异或)
    常用
    1
    xor ax,ax
    对寄存器置零
  • inc自增
  • dec自减
  • 小写字符=大写字符+20h

伪指令

  • dw定义字类型变量,一个字数据占2个字节(16位)单元,读完一个,偏移量加2
  • db定义字节类型变量,一个字节数据占1个字节(8位)单元,读完一个,偏移量加1
  • dd定义双字类型变量,一个双字数据占4个字节(32位)单元,读完一个,偏移量加4
    伪指令db、dw、dd都可以定义字符串,但最多的是用db来定义字符串,第一个原因是dw、dd定义的字符串到了内存中排序是相反的。
  • dup是一个操作符,在汇编语言中同db、dw、dd等一样,也是由编译器识别处理的符号。它是和db、dw、dd等数据定义伪指令配合使用的,用来进行数据的重复。
    dup的使用格式如下:
    db 重复的次数 dup (重复的字节型数据)。
    dw 重复的次数 dup (重复的字型数据)。
    dd 重复的次数 dup (重复的双字数据)。
    dup是一个十分有用的操作符,比如我们要定义一个容量为200个字节的栈段,如果不用dup,则需要大量的代码来进行定义。如果用dup的话:
    1
    2
    3
    stack segment
    db 200 dup (0)
    stack ends
---------------THEEND---------------