常见汇编代码

# 常见汇编代码 #

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

        code segment

        assume cs:code


        mov ax,32

        mov bx,74

        mov cx,23


        sort: 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,4c00h

        code 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:ret

    code 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,0ffffh

    data 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  word

    stack ends


    data segment

            h1  db  'Please input a string: ','$'

            h2  db 'The number of the chars that is not digit:','$'

          crlf  db 0dh,0ah,24h

    data  ends


    code  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,0


    input:    mov    ah,1

            int    21h

            cmp    al,'$'

            jz      exit

            cmp    al,30h

            jb      count

            cmp    al,39h

            jnb    count

            jmp    input


    count:  inc    cx

            jmp    input


    exit:  lea    dx,crlf

            mov    ah,9

            int    21h

            lea    dx,h2

            int    21h


            mov    si,0

            mov    bl,10

            mov    ax,cx


    mem:    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    21H


    main    endp

    code    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为奇数,加1

    exchange: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:data

    start: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 21h


    progrnam 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 input


    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 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',0h

    data ends

    ;------------------------------


    progrnam segment

        assume ds:data,cs:progrnam

    start: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],al

    print: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 21h


    progrnam 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

            ret

    main 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 0

    data 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 next

    progrnam 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

            ret

    progrnam ends

            end begin

16.冒泡排序

ASSUME CS:CODE,DS:DATA

DATA SEGMENT

        BUF DB 12, 32, -2, 4, 0    ; NUMBER ARRAY BUFFER

        CNT DB $-BUF              ; COUNT FOR BUFFER

DATA ENDS

CODE SEGMENT

START:  MOV AX, DATA

        MOV DS, AX                  ; DATA SEGMENT

        MOV SI, OFFSET BUF          ; BUFFER INDEX

        MOV CL, CNT                ; LOOP COUNT

        DEC CL

        MOV CH, 0

OUTER:                              ; OUTER LOOP

        MOV AL, [SI]                ; BUF[SI]

        PUSH CX

        MOV DI, SI                  ; BUFFER INDEX

INNER:                              ; INNER LOOP

        INC DI                      ; DI = SI + 1

        MOV DL, [DI]                ; BUF[DI]

        CMP AL, DL                  ; IF (BUF[SI] > BUF[DI])

        JLE CONT                    ;

        XCHG AX, DX                ; SWAP (BUF[SI], BUF[DI])

        MOV [SI], AL

        MOV [DI], DL

CONT:  LOOP INNER                  ; CONTINUE

        POP CX

        INC SI

        LOOP OUTER

        MOV AH, 4CH

        INT 21H

CODE ENDS

END STA

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容