• call和ret都是转移指令,通过修改IP或CS+IP
    • ret
      • 用栈中的数据修改IP的内容,实现近转移
      • (IP)=((ss)*16+(sp))
      • (sp)=(sp)+2
    • retf
      • 远转移
      • (IP)=((ss)*16+(sp))
      • (sp)=(sp)+2
      • (CS)=((ss)*16+(sp))
      • (sp)=(sp)+2
    • call
      • 过程
        • 将当前的IP或CS+IP入栈
        • jmp
      • 不能实现短转移
      • call 标号
        • (sp)=(sp)-2
        • ((ss)*16+(sp))=(IP)
        • (IP)=(IP)+16位位移(标号处的地址-call指令后第一个字节的地址)
      • call far ptr 标号
        • (sp)=(sp)-2
        • ((ss)*16+(sp))=(CS)
        • (sp)=(sp)-2
        • ((ss)*16+(sp))=(IP)
        • (CS)=标号所在的段地址
        • (IP)=标号所在的偏移地址
      • call 16位寄存器
        • (sp)=(sp)-2
        • ((ss)*16+(sp))=(IP)
        • (IP)= (16位寄存器)
      • call word ptr 内存地址单元
        • push IP((sp)=(sp)-2,((ss)*16+(sp))=(IP))
        • jmp word ptr 内存地址单元((IP)=内存地址单元)
      • call dword ptr 内存地址单元
        • push CS(高位字)
        • push IP(低位字)
        • jmp dword ptr 内存地址单元
    • call&ret

      • 搭配使用
    • mul指令

      • 相乘的两个数位数也要相同
      • 8位:AL中和8位寄存器或内存单元中

    16位:AX中和16位寄存器或内存单元中

    • 结果:8位存储在ax,16位存储在dx(高位)和ax(低位)中
    • 格式:
      • mul reg/mul 内存单元
      • mul byte ptr ds:[0]
      • mul word ptr [bx+si+8]
    • 例题:计算100*10

      1. mov al,100
      2. mov bl 10
      3. mul bl
    • 例题:计算100*10000

      1. mov ax,100
      2. mov bx,10000
      3. mul bx
    • 批量参数的传递,返回值的传递
      • 放在内存中,将内存空间的首地址放在寄存器中
      • 例题:将data段重的字符串转化为大写 ```cpp assume cs:code,ds:data

    data segment db ‘conversation’ data ends

    code segment

    start: mov ax,data mov ds,ax mov si,0 mov cx,12 call capital mov ax,4c00h int 21h

    capital:and byte ptr [si],11011111b inc si loop capital ret

    code ends

    end start

    1. - 例题1show_str,在屏幕83列,用绿色显示字符串
    2. ```cpp
    3. assume cs:code,ds:data
    4. data segment
    5. db 'Welcome to masm!',0
    6. data ends
    7. code segment
    8. start: mov dh,8 ;8行
    9. mov dl,3 ;3列
    10. mov cl,2 ;绿色属性
    11. mov ax,data
    12. mov ds,ax
    13. mov si,0
    14. call show_str
    15. mov ax,4c00h
    16. int 21h
    17. show_str:
    18. push cx
    19. push si
    20. mov al,0A0h ;屏幕一行的字节总数
    21. dec dh ;行号默认从0开始
    22. mul dh ;a从第(n-1)*0A0h处开填写
    23. mov bx,ax ;定位好的位置偏移地址放到bx里
    24. mov al,2 ;每个字符2两字节
    25. mul dl ;定位列,结果ax是列的位置
    26. sub ax,2 ;下表从0开始
    27. add bx,ax
    28. mov ax,0B800h ;显存开始位置
    29. mov es,ax
    30. mov di,0 ;指向显存的偏移地址
    31. mov al,cl
    32. mov ch,0
    33. s:mov cl,ds:[si] ;指向要显示的字符
    34. jcxz ok ;到字符串末尾跳转
    35. mov es:[bx+di],cl ;偶地址存放字符
    36. mov es:[bx+di+1],al ;奇地址存放属性
    37. inc si
    38. add di,2
    39. jmp short s
    40. ok:pop si
    41. pop cx
    42. mov ax,4c00h
    43. int 21h
    44. code ends
    45. end start
    • 例题2:将data段中的数据(12666)以十进制的形式显示(转ASCII) ```cpp ;0~9:30H~39H

    assume cs:code,ds:data

    data segment db 10 dup(0) data ends

    code segment start: mov ax,12666 mov bx,data mov ds,bx mov si,0

    1. call dtoc
    2. mov dh,8
    3. mov dl,3
    4. mov cl,0cah
    5. call show_str
    6. mov ax,4c00h
    7. int 21h

    dtoc:push dx push cx push ax push si push bx

    1. mov bx,0 ;存放位数

    s1:mov cx, 10d ;除数 mov dx,0

    1. div cx
    2. mov cx,ax ;商作为新的除数
    3. jcxz s2
    4. add dx,30h ;余数+30h
    5. push dx ;暂存到栈里
    6. inc bx
    7. jmp short s1

    s2:add dx,30h push dx inc bx

    1. mov cx,bx
    2. mov si,0

    s3:pop ax mov [si],al inc si loop s3

    okay:pop bx pop si …

    1. mov ax,4c00h
    2. int 21h

    code ends end start ```