汇编第二次试验

来源:互联网 发布:mysql group by 索引 编辑:程序博客网 时间:2024/05/18 01:30

  这次实验有三个题目,用了一整天时间,收获颇丰,最重要的是思想上的冲击!让我真的感觉到汇编语言和高级语言的想法就是不一样!

心路历程:其实写汇编真的思维和写其他高级语言完全不同,因为汇编它是要么顺序执行A,要么跳转到B执行,但是有可能顺序执行后A根据题意是不能执行B的,于是就出现矛盾了,或者根本就跳转不回来!!如下例子:

   其实感觉写汇编的跳转指令有点像提取公因式!把无论是顺序执行还是跳转执行的相同部分放在最后,让他们能够顺序执行完,否则将会出现矛盾!

DATAS SEGMENT

    array dw 3 DUP(0)

    flag  db 0;这个最大的缺点就是会重复计算因为A1=A2=A3判断3次其实应该是

DATAS ENDS     ;输出2,但实际它输出的却是3


STACKS SEGMENT

    ;此处输入堆栈段代码

STACKS ENDS

 

CODES SEGMENT

    ASSUME CS:CODES,DS:DATAS,SS:STACKS

START:

    MOV AX,DATAS

    MOV DS,AX

    mov flag,0;设置一个标志位

    mov si,0 ;设置初始偏移地址

    mov cx,3

    

Input:

    mov ah,01h;循环输入数字

    int 21h

    mov ah,0h

    mov ds:array[si],ax;把输入的数字赋值给存储器

    inc si

    loop Input

       

    mov si,0;重置si为0

    mov cx,2;重置cx为2

    

Compare:

    mov ax,ds:array[si]

    mov bx,ds:array[si+1]

    cmp ax,bx

    jz count   这里本来想计数,但是跳入

    inc si   

    loop Compare

    

    mov ax,ds:array[0]

    mov bx,ds:array[2]

    cmp ax,bx

    jz count

    

count:这里后!!就回不来了!,如果再写一个jmp Compare,那么程序每次顺序执行到这里时就不停跳转,进入死循环!!!但是高级语言直接if(){count++;}就可以了!

    add flag,1


sub flag,1

    mov dl,0ah

    mov ah,02h

    int 21h

    

    mov dl,0dh

    mov ah,02h

    int 21h

   

add flag,30h

    mov dl,flag

    mov ah,02h

    int 21h

             

    MOV AH,4CH

    INT 21H

CODES ENDS

    END START



1.试编写一汇编语言程序,要求从键盘接收一个4位的16进制数,并在终端上显示与它等值的二进制数。

  

DATAS SEGMENT

   

     ; head db "please enter 4 integers: $";

    ;此处输入数据段代码  

DATAS ENDS


STACKS SEGMENT

    ;此处输入堆栈段代码

STACKS ENDS


CODES SEGMENT

    ASSUME CS:CODES,DS:DATAS,SS:STACKS

START:

    MOV AX,DATAS

    MOV DS,AX 

    mov ch,4 ;用于输入循环使用

    mov cl,4 ;用于 bx移位使用

    sub bx,bx ;初始化 bx

    sub ax,ax ;初始化 ax

    sub dx,dx ;初始化 dx

 

input:

    mov ah,1h ;输入一个 16进制数字

    int 21h

    sub al,30h ;存进去是 ASCII,先判断是不是数字

    jl   exit ;如果该数字小于 0就跳出

    cmp al,9d ;判断是不是 0-9,把它变为 16进制的 0-9

    jle  printit ;是 0-9,就跳转到 printit

    sub al,7h ;不是 0-9,把它变成 16进制的 A-F

   

printit:

            ;and al,0fh;把al 的高四位清零,注意注意!!可能覆盖!!

            ;mov bl,al;把al 的数据传给bl

    shl bx,cl ;将 bx左移 4位,第一个输入的数据存在了 bl的高四位

    or  bl,al

    dec ch ;将 ch-1

    jnz input;如果 ch不为 0,就继续输入一个数字


   sub cx,cx

   mov cx,16

  

   mov dl,0dh

   mov ah,2

   int 21h

  

   mov dl,0ah

   mov ah,2

   int 21h

output:  

    mov dl, '0'

    shl bx,1 ;将 bx左移一位,最高位存在 CF里

    jnc action;如果 CF=0就跳到action0

    mov dl, '1'

          ;jc  action1;如果CF=1 就跳到action1

   

action:

    mov ah,02

    int 21h

   

loop output

  

exit:

    ret

    MOV AH,4CH

    INT 21H

CODES ENDS

    END START

(1)要注意的是:当用户输入一个一个数字或者字母,它存放在系统里面是一个ASCII值,比如输入9d,它存的其实是39h,所以要先判断,所以要sub al,30h ;存进去是 ASCII,先判断是不是数字

                             不是就在判断是不是字母,如果是0-9就直接跳入printit,注意无论是字母还是数字都要执行printit,所以可以它直接安排在后面!!

(2)要把数据全部存入bx中,要移位!注意!

      shl bx,cl

       要把如果是数字则只能是1!即 shl bx,1,否则必须要用cl先把数字存起来!!

(3)用or把al和bl对接!其实BX向左移动四位,那么bl都是有空间的,所以不用or ax,bx,用dec ch,让ch自减去1再循环!

(4)虽然数字都存进去了,但是输出的时候汇编会把它自动识别为ASCII码!!!例如下图:

所以还是用shl一位一位的把数字存到CF里,再通过jnc识别!最后输出!!注意这里的dl里的数字不同,所以不能都写在action里!!

2.

用15行*16列的表格形式显示ASCII码为10H-FFH的所有字符(双重循环程序)

DATAS SEGMENT

    ;此处输入数据段代码  

DATAS ENDS


STACKS SEGMENT

    ;此处输入堆栈段代码

STACKS ENDS


CODES SEGMENT

    ASSUME CS:CODES,DS:DATAS,SS:STACKS

START:

    MOV AX,DATAS

    MOV DS,AX

   

    mov dx,0010h ;先将 dx的赋初值为 0010h

first:

    mov cx,10h ;将计数寄存器的初值定为 16次,因为有 16列

second:

    mov ah,02h

    int 21h

    inc dx

    push dx ;第一次的话就是保存 dx中 0011h内容

    mov dl,0

    mov ah,02

    int 21h

    pop dx

    loop second

   

    push dx

   

    mov dl,0dh ;显示回车

    mov ah,02h

    int 21h

   

    mov dl,0ah ;显示换行

    mov ah,02h

    int 21h

   

    pop dx

    cmp dx,100h ;;由于这里是小于才跳转,如果采用 cmp dx.0ffh

    jb first;那么还没有显示 0ffh,程序就执行完了,所以要跟 100h比较

   

   

    MOV AH,4CH

    INT 21H

CODES ENDS

    END START


  这个实验最大的亮点就是用了PUSH和POP来保存dx的内容,这样就不用把数据暂存于其他的寄存器中了!!而且比较的是100h而不是0ffh因为最后一个会无法显示!

3.

编写一程序,要求比较数组Array中的三个16位补码数,并根据比较结果在终端上显示如下信息:

1、如果三个数都不相等则显示0;

2、如果三个数有两个数相等则显示1;

3、如果三个数都相等则显示2。

DATAS SEGMENT

    array dw 3,3,3

    ;array dw 3,4,5

    ;array dw 3,4,3;此处输入数据段代码  

DATAS ENDS


STACKS SEGMENT

    ;此处输入堆栈段代码

STACKS ENDS


CODES SEGMENT

    ASSUME CS:CODES,DS:DATAS,SS:STACKS

START:

    MOV AX,DATAS

    MOV DS,AX

   

compare12:   

    mov ax,ds:array[0] ;先比较第一个和第二个数 ,OPRT1和OPRT2 可以是寄存器或存储器

    cmp ax,ds:array[2] ;但不能同时为存储器, OPRT2还可以为立即数。

    jnz compare23     ;所以要把其中一个赋值给 ax

                      ;如果不相等则跳转到 compare23,比较第一个数和第三个数

                     

compare32:            ;相等就顺序执行 compare32,因为相等判断的次数少一些

    mov ax,ds:array[2] ;最后直接跳到 output就可以出去

    cmp ax,ds:array[4]

    mov dl,32h        ;A1=A2=A3先把2 存入dl这样跳转到 output可以直接使用输出2

    jz  output        ;相等就输出 2

    mov dl,31h        ;A1=A2!=A3不相等就把1 移入dl

    jmp output        ;无条件跳入 output输入

   

compare23:  ;第一个数与第二个数不相等跳入!

    mov ax,ds:array[2]

    cmp ax,ds:array[4]

    jnz compare13 ;不相等跳入 compare13

    mov dl,31h    ;A1!=A2=A3否则将1 移入dl

    jmp output    ;无条件跳转

   

compare13: ;比较第一个数与第三个数

    mov ax,ds:array[0]

    cmp ax,ds:array[4]

    mov dl,30h ;A1!=A2!=A3

    jnz output

    mov dl,31h ;A1!=A2,A2!=A3 ,A1=A3

   

output: ;要把 output放在最后,因为前面所有的程序都要执行到它!!

    mov ah,02h

    int 21h   

     

    MOV AH,4CH

    INT 21H

CODES ENDS

    END START

注意!!!短的判断内容先写,直接跳出,因为写在后面长的判断很可能会经过短的判断!!


0 0
原创粉丝点击