汇编语言学习笔记2

时间:2022-08-30 03:29:23

更灵活的定位内存地址的方法

以字符形式给出的数据:
使用关键字db

assume cs:code

data segment
    db 'unix'
    db 'fork'
data ends

code segment
start:  mov al, 'a'
        mov bl, 'b'
        mov ax, 4c00h
        int 21h
code ends
end start

查看ds+10h段内存单元
汇编语言学习笔记2

实现大小写的转换
观察大小写字母的ASCII码值可以发现,大写字母和小写字母的第5位ASCII码值是不一样的,也就是小写字母正好比大写字母的ASCII**大20H**
所以我们只需要使用AND和OR操作来改变第5位的值就行了

assume cs:codesg, ds:datasg

datasg segment
    db 'BaSiC'
    db 'iNfOrMaTiOn'
datasg ends

codesg segment
start:  mov ax, datasg
        mov ds, ax
        mov bx, 0
        mov cx, 5            ;将BaSiC转换为basic
    s:  mov al, [bx]
        and al, 11011111B
        mov [bx], al
        inc bx
        loop s

        mov bx, 5
        mov cx, 11          ;将iNfOrMaTiOn转换为INFORMATION
    s0: mov al, [bx]
        or al, 00100000B
        mov [bx], al
        inc bx
        loop s0

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

程序执行完毕之后,BaSiC和iNfOrMaTiOn分别被改成了大写和小写
汇编语言学习笔记2

下面给出了一种更加灵活的定位内存单元的方法

mov ax, [200+bx]
mov ax, 200[bx]
;这个形式和高级语言中的a[i]b[i]非常相像
mov ax, [bx].200  
这上面三中写法其实是一个意思:
    将段地址为ds,偏移地址为200+bx的内存单元中的数值存到寄存器ax

有了这种定位内存位置的方式,我们就可以处理数组了,是用这种方式,上面的那段大小写转换程序不需要使用设置两个循环了
代码如下:(处理的两个单词的长度必须是一样的。。。。

assume cs:code, ds:datasg

datasg segment
    db 'BaSiC'
    db 'MinIX'
datasg ends

code segment
    start:  mov ax, datasg
            mov ds, ax 
            mov bx, 0

            mov cx, 5
        s:  mov al, [bx]
            and al, 11011111b
            mov [bx], al
            mov al, [5+bx]
            or al, 00100000b
            mov [5+bx], al
            inc bx
            loop s

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

处理前:
汇编语言学习笔记2
处理后:
汇编语言学习笔记2

嵌套循环(双层循环)
程序代码:

assume cs:code, ds:datasg

datasg segment
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    ;将这六行每一行的前四个单词变成大写
datasg ends

code segment 
    start:  mov ax, datasg
            mov ds, ax
            mov bx, 0

            mov cx, 6
        s0: mov dx, cx       
            mov si, 0

            mov cx, 4
        s:  mov al, [bx+si]
            and al, 11011111b
            mov [bx+si], al
            inc si
            loop s
            add bx, 10h
            mov cx, dx
            loop s0

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

处理前:
汇编语言学习笔记2
处理后:
汇编语言学习笔记2
注意:我们这段程序只是两层嵌套,必然需要使用两个循环因子,我们上面的这段程序使用的是寄存器,但是CPU中的寄存器的数量是有限的,当我们的程序非常复杂的时候,使用寄存器来做循环因子就不那么现实了,这时候我们就寻要用内存了,对上面程序的改进如下:

assume cs:code, ds:datasg

datasg segment
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
datasg ends

code segment 
    start:  mov ax, datasg
            mov ds, ax
            mov bx, 0

            mov cx, 6
        s0: mov ds:[400h], cx        
            mov si, 0

            mov cx, 4
        s:  mov al, [bx+si]
            and al, 11011111b
            mov [bx+si], al
            inc si
            loop s
            add bx, 10h
            mov cx, ds:[400h]
            loop s0

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

我们原先是使用寄存器dx来暂存cx中的数值的,现在改用内存空间ds:[400h]来暂存cx的值,就摆脱了寄存器数量的限制

对于上面的程序,我们还有需要改进的地方,使用内存来暂存循环因子寄存器的值肯定是没错的,但是我们应该选择栈作为存储的数据结构,来使得我们的程序条理更加的清楚,每添加一个内层循环,我们就将当前循环因子的值push进栈,每结束一个循环,我们就pop一个值到cx中,这样才是最合理的,改进后的代码如下:

assume cs:code, ds:datasg, ss:stacksg

datasg segment
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
    db 'file '
datasg ends

stacksg segment
    dw 0,0,0,0,0,0,0,0
stacksg ends

code segment 
    start:  mov ax, datasg
            mov ds, ax
            mov ax, stacksg
            mov ss, ax
            mov sp, 10h
            mov bx, 0

            mov cx, 6
        s0: push cx      
            mov si, 0

            mov cx, 4
        s:  mov al, [bx+si]
            and al, 11011111b
            mov [bx+si], al
            inc si
            loop s
            add bx, 10h
            pop cx
            loop s0

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

仅仅是申请一段栈空间,然后把前面的代码中的mov ds:[400h], cx和mov cx, ds:[400h]改成了push cx和pop cx,程序就变得清晰了许多