汇编源码

# 常见汇编代码 #

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

很抱歉,根据提供的引用内容,我无法直接回答你关于printf汇编源码的问题。引用和引用提供的内容与printf汇编源码无关。如果你需要了解printf函数的汇编实现,我可以为你提供一些相关的信息和示例代码。 printf函数是C语言中用于格式化输出的函数。它可以根据指定的格式字符串将数据输出到标准输出设备(通常是终端窗口)。printf函数的汇编实现通常是由编译器生成的,具体的实现方式可能因编译器和平台而异。 如果你想了解printf函数的汇编实现,你可以参考特定编译器的文档或查看相关的汇编代码示例。不同的编译器和平台可能有不同的实现方式,因此具体的汇编源码会有所不同。 如果你对printf函数的汇编实现感兴趣,我可以为你提供一些示例代码,展示如何使用汇编语言实现简化版的printf函数。请注意,这只是一个简化的示例,实际的printf函数实现要复杂得多。 ```assembly section .data format db "%s %d %hd", 0 section .text global _start _start: ; 保存寄存器状态 pusha ; 准备参数 mov eax, 1 mov ebx, message mov ecx, 123 mov dx, 456 ; 调用printf函数 call printf ; 恢复寄存器状态 popa ; 退出程序 mov eax, 1 xor ebx, ebx int 0x80 printf: ; 保存寄存器状态 pusha ; 打印字符串 push ebx push format call printf_internal add esp, 8 ; 打印整数 push ecx push edx push format + 3 call printf_internal add esp, 12 ; 恢复寄存器状态 popa ret printf_internal: ; 保存寄存器状态 pusha ; 打印参数 push ebp mov ebp, esp sub esp, 4 mov eax, [ebp + 8] push eax push format call printf_scanf add esp, 8 mov esp, ebp pop ebp ; 恢复寄存器状态 popa ret printf_scanf: ; 保存寄存器状态 pusha ; 调用系统调用打印字符串 mov eax, 4 mov ebx, 1 mov edx, [esp + 4] mov ecx, [esp + 8] int 0x80 ; 恢复寄存器状态 popa ret section .data message db "Hello, world!", 0 ``` 这是一个简化的汇编代码示例,展示了如何使用汇编语言实现一个简单的printf函数。它可以打印字符串、整数和短整数。请注意,这只是一个简化的示例,实际的printf函数实现要复杂得多。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值