常见汇编代码

来源:互联网 发布:怎样制作炒股票软件 编辑:程序博客网 时间:2024/06/05 07:03

常见汇编代码

  1. 编写程序:比较AX,BX,CX中带符号数的大小,将最大的数放在AX中

    code segment assume cs:code  mov ax,32 mov bx,74 mov cx,23sort: cmp ax,bx       jge X          ;如果ax大于等于bx就跟cx比较      xchg ax,bx     X:cmp ax,cx       ;如果ax大于cx      jge Y      xchg ax,cx      Y:int 21h       mov ax,4c00hcode ends     end sort

2.要求对键盘输入的小写字母用大写字母显示出来

    code segment      assume cs:code     start: mov ah,1        int 21h         cmp al,'a'               jz error         cmp al,'z'        ja error         sub al,20h       ;'A'~'Z':41~5AH     ‘a'~'z':61~7ah        mov dl,al         mov ah,2         int 21h         jmp start    error:retcode ends      end start

3.编写程序:从键盘上接收一个四位数的十进制数,并在终端上显示出与它等值的二进制数。

    code segment       assume cs:code     begin:xor bx,bx       ;清空bx          mov ch,4          mov cl,4        ;设置内外层的循环次数    input:shl bx,cl        ;bx中的内容逻辑左移          mov ah,1          int 21h          ;输入          cmp al,30h        ;是否小于0          jb  input         ;是就重新输入          cmp al,39h        ;是否大于9          ja  input                and al,0fh        ;转换为相应的二进制          jmp combine    combine:or bl,al                     dec ch             jnz input     display:mov cx,16        ;输出的循环次数       print:mov dl,0              rol bx,1              rcl dl,1              or dl,30h        ;清空dl             mov ah,2              int 21h              loop print              ret    code ends          end begin 

4.将内存ffff:0~ffff:d单元中的数据复制到0:200~0:20d单元中。

code segment assume cs:code         mov bx,0         mov cx,0fh  copy:mov ax,0ffffh          mov ds,ax       mov dl,[bx]      mov ax,0020h      mov ds,ax       mov [bx],dl      inc bx       loop copy     mov ax,4c00h     int 21h code  ends       end copy 

5.将AX寄存器中的16位数分成四组,每组四位,然后把这四组数分别放在AL、BL、CL和DL中。

data segment   s db 4 dup(?)   ;占位,并清空  mov ax,0ffffhdata ends ;-----------------------------------     progrnam segment           assume cs:progrnam,ds:data begin:mov cl,4     ;ax逻辑右移四次       mov ch,4            lea bx,s  X: mov dx,ax     and dx,0fh      ;逻辑与屏蔽高位     mov [bx],dl   ;以字节形式将dl移入bx     inc bx      shr ax,cl       ;逻辑右移     dec ch      jnz X  Y: mov dl,s        ;依次移入相应寄存器内     mov cl,s+1     mov bl,s+2      mov al,s+3     ret     progrnam ends     end begin

6.从键盘输入一系列字符,以字符‘$’为结束符,然后对其中的非数字字符计数,并显示出计数结果。

`stack segment     dw  100h    dup(?)     top  label   wordstack endsdata segment        h1   db  'Please input a string: ','$'        h2   db 'The number of the chars that is not digit:','$'       crlf  db 0dh,0ah,24hdata   endscode  segment      assume  cs:code,ds:data,ss:stack main  proc    far  begin:mov     ax,stack         mov     ss,ax        lea     sp,top        mov     ax,data         mov     ds,ax        lea     dx,h1    mov ah,9    int 21h        mov     cx,0input:     mov     ah,1        int     21h        cmp     al,'$'        jz      exit        cmp     al,30h        jb      count         cmp     al,39h        jnb     count         jmp     inputcount:  inc     cx        jmp     inputexit:   lea     dx,crlf        mov     ah,9        int     21h        lea     dx,h2        int     21h        mov     si,0        mov     bl,10        mov     ax,cxmem:     div     bl        mov     dl,ah        mov     dh,0        push    dx        inc     si        mov     ah,0        cmp     al,0        jnz     mem prin:     pop     dx        add     dl,30h        mov     ah,2        int     21h        dec     si        cmp     si,0        jnz     prin        mov     ah,4ch        int     21Hmain    endpcode    ends        end   begin `

7.已知两个整数变量A和B,试编写完成下述操作的程序:
(1)若两个数中有一个数是奇数,则将奇数存入A中,偶数存入B中
(2)若两个数均为奇数,则两数分别加1,并存回原变量。
(3)若两个数均为偶数,则两变量不变。

code segment     assume cs:code begin: mov ax,13       mov bx,12       mov cx,ax        mov dx,bx        xor ax,bx        test ax,0001h    ;A和B是否同时为奇数或偶数       jz next           ;是       test bx,0001h           jz return        ;B为偶数,A为奇数,加1exchange:mov ax,dx        ;A为偶数,B为奇数,交换       mov bx,cx        jmp return   next:test bx,0001h    ;是否同为奇数       jz return        ;同为偶数,不变       inc dx         inc cx       jmp exchange  return:ret code ends       end begin

8.比较两个字符串string1和string2所含的字符是否相同。若相同则显示‘true’,否则显示‘false’。

 data segment      string1 db 'i am a student'     string2 db 'i am a student'     string3 db 'true',0dh,0ah,'$'     string4 db 'false',0dh,0ah,'$'data ends ;--------------------------  progrnam  segment       assume cs:progrnam,ds:datastart:push ds       sub ax,ax      push ax       mov ax,data      mov ds,ax      mov es,ax begin:lea si,string1      lea di,string2      cld          mov cx,string2-string1      repe cmpsb      jne Y      lea dx,string3      jmp print         Y:lea dx,string4    print: mov ah,9       int 21h     mov ax,4c00h    int 21hprogrnam ends      end start

9.编写无溢出除法的汇编子程序 。

这里所说的除法溢出并不是指分母为0而发生溢出的情况。我们以除数为8位的情况来说明,假设我们的被除数为65535(16位的最大值)存储在AX 中,除数为1,存储在CL中,然后执行除法指令: div CL。根据上面的说法,结果都是放在AX中的,余数为0,当然这没有问题,然而商为65535要放在AL中却是放不下的,因为AL能存放的最大值只为 255,所以此时就会发生溢出。我们可以看到65535/1 = 255,这显然与我位正常的除法结果不符。
如何解决这个溢出问题
既然我们知道了问题的根源,要解 决它就不困难了。为了统一而且不发生溢出,我们可以把所有的除法的商都用32位来保存,即所有的被除数都用32位,所有的除数都用16位,所有的商都用 32位,所有的余数都用16位来保存,就可以解决这个问题,因为一个数除以一个整数后,不可能大于其之前的值。而对于8位的除法,除数和被除数的高位全用 0补全即可。为了达到这个目的,我们就不能使用默认的除法指令div了,而需要我们写代码来实现我们自定义的除法。

自定义除法: X为除数,N为被除数,H代表X的高16位,L代表X的低16位,
int(H/N)和rem(H/N)代表着H除以N的商和余数
X/N = int(H/N)* 2^16 + [rem(H/N)* 2^16+L]/N

 progrnam segment          assume cs:progrnam           mov ax,0ffffh          mov cx,1           ;初始化进行测试 begin: cmp cx,0        je return   ;除数不能为0        push bx          push ax        mov ax,dx         mov dx,0         div cx  ;执行H/N,商保存在ax中,余数在DX中        mov bx,ax ;把商保存         pop ax    ;取出低位,执行rem(H/N)*2^16+L        div cx    ;执行[rem(H/N)*2^16+L]/N ,商保存在ax中 ,余数在dx中        mov cx,dx ;cx保存余数        mov dx,bx ;dx中保存高位除法的商        pop bx return:ret     mov ax,4c00h    int 21h progrnam ends        end begin

10.编写一个程序,接受从键盘输入的10个十进制数字,输入回车符则停止输入,然后将这些数字加密后(用XLAT指令变换)存入内存缓冲区BUFFER。加密表为:

输入数字:0,1,2,3,4,5,6,7,8,9

密码数字:7,5,9,1,3,6,8,0,2,4

data segment     number db 7,5,9,1,3,6,8,0,2,4     buffer db 10 dup(?)data ends ;-------------------------------------code segment      assume cs:code,ds:data      mov si,0     mov cx,10      lea bx,number input:mov ah,1       int 21h      cmp al,0dh    ;是否为回车符      jz return      cmp al,30h    ;比较是否是0~9,不是就重新输入      jb input       cmp al,39h      ja input       xlat           ;变换进行存储      mov buffer[si],al       inc si       loop input return:ret code ends end inputdata segment     number db 7,5,9,1,3,6,8,0,2,4     buffer db 10 dup(?)data ends ;-------------------------------------code segment      assume cs:code,ds:data      mov si,0     mov cx,10      lea bx,number input:mov ah,1       int 21h      cmp al,0dh    ;是否为回车符      jz return      cmp al,30h    ;比较是否是0~9,不是就重新输入      jb input       cmp al,39h      ja input       xlat           ;变换进行存储      mov buffer[si],al       inc si       loop input return:ret code ends      end input

11.编写一个子程序嵌套结构的程序模块,分别从键盘输入姓名及8个字符的电话号码,并以一定的格式显示出来。

主程序TELIST:A.  显示提示符“INPUT  NAME:”;B.  调用子程序INPUT_NAME输入姓名;C.  显示提示符“INPUT  A  TELEPHONE  NUMBER:”;D.  调用子程序INPHONE输入电话号码;E.  调用子程序PRINTLINE显示姓名及电话号码。子程序INPUT_NAME:A.  调用键盘输入子程序GETCHAR,把输入的姓名存放在INBUF缓冲区中;B.  把INBUF中的姓名移入输出行OUTNAME。子程序INPHONE:A.  调用键盘输入子程序GETCHAR,把输入的8位电话号码存放在INBUF缓冲区中;B.  把INBUF中的号码移入输出行OUTPHONE。子程序PRINTLINE:显示姓名及电话号码,格式为:  NAME  TEL.  X X X     XXXXXXXX

代码如下:

data segment     tipname db 'input name:','$'     tipnumber db 'input a telephone number:','$'     inbuf db 12 dup(' ')     crlf db 0dh,0ah,'$'     outname db 16 dup(' ')     outphone db 12 dup(' '),0dh,0ah,'$'     info db 'name',12 dup(' '),'tel',0dh,0ah,'$'data ends;------------------------------------stack segment        dw 100 dup(?)      ;伪定义使得同一个变量具有不同的属性    string label word    stack ends ;----------------------------------------progrnam segment  main proc far       assume cs:progrnam,ds:data,es:data,ss:stack   start:mov ax,stack        mov ss,ax         mov sp,offset string         push ds         xor ax,ax         push ax         mov ax,data         mov ds,ax         mov es,ax   begin:                         mov ah,09          ;输出提示字符串         mov dx,seg tipname         mov ds,dx          mov dx,offset tipname         int 21h         call input_name    ;输入姓名         mov ah,09           ;输出提示字符串         mov dx,seg tipnumber         mov ds,dx          mov dx,offset tipnumber         int 21h          call input_number          call printline               ret main endp  ;------------------------------------------ input_name proc near            call getchar             lea si,inbuf            lea di,outname            mov cx,12      ;设置计数器            cld             ;设置方向为自增;movsb 与rep结合是传送字节,相当于 movs es:byte ptr[di],ds:[si]            rep movsb                   ret input_name endp ;-----------------------------------------------input_number proc near          call getchar          lea si,inbuf          lea di,outphone         mov cx,12          cld          rep movsb          ret input_number endp ;------------------------------------------------getchar proc near        mov al,20h         mov cx,12          lea di,inbuf        cld ;stosb这里是为了每一次输入一个字节存入相应的缓冲区        rep stosb         mov cx,12         mov di,0    input:mov ah,1          int 21h          cmp al,0dh         jz return         mov inbuf[di],al          inc di          loop input    return: call disp_crlf           ;输出回车符            ret getchar endp ;--------------------------------------printline proc near             ;这里均是将所得的字符串进行输出          mov ah,09          mov dx,seg info          mov ds,dx           mov dx,offset info          int 21h           mov ah,09          mov dx,seg outname          mov ds,dx           mov dx,offset outname          int 21h           ret printline endp ;---------------------------------------disp_crlf proc near          mov ah,09          mov dx,seg crlf          mov ds,dx           mov dx,offset crlf          int 21h           ret disp_crlf endp ;-----------------------------------------progrnam ends          end start

12.试编写一个汇编语言子程序,要求将包含任意字符、以0结尾的字符串中的小写字母转换成大写字母。

data segment      string db 'i am A stuDEnt',0hdata ends;------------------------------progrnam segment     assume ds:data,cs:progrnamstart:push ds     xor ax,ax        mov ax,data       mov ds,ax     lea si,string     push si     begin: mov al,[si]      ;判断是否为小写字母并进行转换      cmp al,0      je return         cmp  al,'a'      jb print      cmp  al,'z'      ja print           ;如果不是小写字母直接进行输出      sub al,20h      mov [si],alprint:push ds           ;将字母进行输出      ;mov al,[si]      mov dl,al      mov ah,2      int 21h      pop ds          n:inc si      jmp begin      return:      pop si      pop ds    mov ax,4c00h    int 21hprogrnam ends    end start  

13.编写程序,将一个包含有20个数据的数组M分成两个数组:正数数组P和负数数组N,并分别把这两个数组中数据的个数显示出来。

data segment    string1 db 0dh,0ah, 'positive number:','$'    string2 db 0dh,0ah,'negative number:','$'    array dw  1,2,3,4,5,6,7,8,-4,-8,-9,-6,-2,-8,8,12,18,-12,5,64    array1 dw 20 dup(?)     ;存储正数数组    array2 dw 20 dup(?)      ;存储负数数组    count1 db 0    count2 db 0               ;计数    CRLF DB 0dh,0ah,'$'data ends;----------------------------------progrnam segment main proc far     assume ds:data,cs:progrnam    s:   push ds         xor ax,ax        push ax         mov ax,data         mov ds,ax        begin:mov cx,20         ;循环次数          lea bx,array      ;bx相当于数组的首地址          lea si,array1          lea di,array2      start:mov ax,[bx]            cmp ax,0         ;是否为负数            js Y             ;是负数            mov [si],ax       ;存入正数数组            inc count1             add si,2             jmp short next          Y:  mov [di],ax             inc count2            add di,2         next:add bx,2              loop start         lea dx,string1         mov al,count1         call print         lea dx,string2        mov al,count2               call print        retmain endp        ;--------------------------------------print  proc near        push ax      ;al中存储计数值,要进行保存        mov ah,9         int 21h        pop ax        ;出栈,进行ASCII码调整        aam            ;调整方式AH<-AL/10(商),AL<-AL%10         push ax          add ah,30h  ;变为0~9的ASCII码        mov dl,ah         mov ah,2        int 21h        pop ax         add al,30h         mov dl,al         mov ah,2        int 21h        lea dx,CRLF        mov ah,9         int 21h         ret print endp progrnam ends         end s

14.设有10个学生的成绩分别是76,69,84,90,73,88,99,63,100和80分。试编制一个子程序统计60~69分,70~79分,80~89分,90~99分和100分的人数,分别存放到S6,S7,S8,S9和S10单元中。

data segment     grade dw 76,69,84,90,73,88,99,63,100,80     count1 dw 0     count2 dw 0     count3 dw 0     count4 dw 0     count5 dw 0data ends;-----------------------------------------progrnam segment          assume ds:data,cs:progrnam           push ds          xor ax,ax           push ax           mov ax,data           mov ds,ax     begin:mov cx,10    mov si,0    next:mov ax,grade[si]         mov bx,10          div bl          mov bl,al          sub bx,6          sal bx,1    ;将(grade/10-6)×2就是         inc count1[bx]  ;count1是首地址         add si,2    loop nextprogrnam ends      end begin

15.输出空行

progrnam segment         assume cs:progrnam    begin:push cx          push dx          mov ax,3    ;这里对ax进行赋值,观察输出的结果          mov cx,ax    print:mov dl,0dh          mov ah,2    ;这是对与输出一个字符的bios的调用          int 21h  ;print的功能就是输出空行,0dh为回车        mov dl,0ah ;0ah为换行        mov ah,2        int 21h         loop print        pop dx        pop cx    ;这一段程序是为了测试输出后的结果,主要母的是输出一个黄色的'*'        mov ah,9        mov al,'*'        mov bh,0         mov bl,0eh        mov cx,1        int 10h        retprogrnam ends         end begin
0 0