乐趣区

关于读书笔记:王爽汇编语言第4版读书笔记第910章

写这个系列文章的次要目标是记录书中重要的知识点,并和大家分享一些集体了解与实际。因为笔记中的知识点比拟零散,而书中零碎的介绍了一个 x86-16 处理器在实模式下的工作原理以及如何应用汇编语言与其进行“沟通”,所以举荐想要零碎学习的敌人们去学习这本书。当咱们把握了实模式的工作原理之后,就能够进一步钻研起初呈现的其余运行模式(如保护模式)。除此之外,相熟汇编语言有助于咱们把握下层语言(如 C)的执行原理,因为它们都要对汇编(机器码)进行形象,而汇编程序就是基于 CPU 的执行机理写进去的。

第九章

转移 行为 分类

  • 段内转移 (只批改 IP, 依据转移的范畴不同又分为: 短转移 近转移
  • 段间转移(同时批改 CSIP

jmp 指令的两种实现差别

在个别的汇编指令中,立刻数不管示意一个数据还是内存单元的偏移地址,都会在对应的机器指令中呈现

  1. 基于 转移的间隔 ——指令中不蕴含目标地址,而蕴含的是 位移量(向前或向后挪动的间隔)

    • 长处,可 浮动拆卸,即位移量不变的状况下,这段程序可在任何中央执行
  2. 基于要转移的目标地址

以上两个维度的汇总

基于转移的间隔(间接转移) 基于要转移的目标地址(间接转移)
段内转移 jmp short Label
jmp Labeljmp near ptr Label
jmp 某一非法 16 位寄存器——将寄存器中的内容写入 IP
jmp word ptr 地址——转移到目标偏移地址
段间转移 jmp far ptr Label(注:它也可能实现段内转移的成果)
jmp dword ptr 地址h_word= 段地址,l_word= 目标偏移地址)
  • jmp short Label: 翻译成的机器码为 EB??H , ?? 代表 8 位的位移量(这种形式是 短转移

    实质为:IP = IP + 8 位的位移量【重点(容易被疏忽):CPU 在执行该指令时,是应用这个位移量来计算 IP 的】- short 指明此处的位移为 8 位位移,范畴是 -128~127, 用【补码】示意
    - 8 位的位移量 = 标号处的地址 - jmp 指令后的第一个字节的地址,编译器在【编译时】算出
    • 为什么是 jmp 指令后的第一个字节的地址 aj?为什么这么设计呢?因为取址之后(执行之前)IP 寄存器中的地址会被设置为该地址aj,这样在执行转移指令时,能够直接参与目标偏移地址的计算!

      • 编译时:disp=as-aj, 执行指令时:IP(as) = IP(aj) + disp(位移量) 即间接实现该指令的性能
  • jmp near ptr Label近转移,实质与短转移雷同,区别仅仅是它反对16 位的位移量
  • jmp far ptr Label远转移

    CS 设置为 标号所在段的【段地址】IP 设置为 标号在该段中的【偏移地址】

masm 对 jmp 外部转移的编译实现

【条件转移】和【循环指令】是对【短转移】的性能扩大

  • jcxz 指令的伪代码:

       ......
    
       if ((cx) == 0) {jmp short s}
    
    s: ......
  • loop 指令的伪代码

    s: ......
    
       (cx)--;
       if ((cx) != 0) {jmp short s}
    
       ......

试验八:剖析一个奇怪的程序

留神:是将 jmp short s1 的机器码 EBF6 拷贝至 076C:0008~076C:0009 两个存储单元中,F6-10 的补码,示意位移量

其实 补码 F6 示意什么有符号数,能够不必图片中的办法计算,而应用以下办法计算更为简略:

  • 因为补码 1111 1111 示意十进制有符号数 -1, 这个 -1 的计算形式是:

    $$
    -1 = -1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 1*2^3 + 1*2^2 + 1*2^1 + 1*2^0
    $$

    $$
    = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1
    $$

  • 那么补码 1111 0110(0xF6) 就等于:

    $$
    -1*2^7 + 1*2^6 + 1*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 1*2^1 + 0*2^0
    $$

    $$
    (-1*2^7+1*2^6+1*2^5+1*2^4+1*2^3+1*2^2+1*2^1+1*2^0) – 1*2^3 – 1*2^0 = -1 – 8 – 1 = -10
    $$

试验九:80x25 黑白字符模式缓冲区输入程序

  • 显示缓冲区:B8000H~BFFFFH(共 32KB, 8 页,每页 4KB)
  • 80x25——每页由 25 行组成,每行由 80 个字符(160byte)组成
  • 注:dosbox 中执行完可执行文件,输入后果会被向上顶一行(弹出输出提示符导致),所以以下程序的输入就显示在 11,12,13 行了
; 在屏幕两头别离显示黑底绿色、绿底红色、白底蓝色的字符串 'welcome to masm!'
; 题目要求屏幕两头显示?那就 12,13,14 行显示
assume cs:codesg, ds:datasg, ss:stacksg

datasg segment
    db 'welcome to masm!'
    db 02H, 24H, 71H ; 三种属性:黑底绿色、绿底红色、白底蓝色
datasg ends

stacksg segment
    dd 0,0,0,0
stacksg ends

codesg segment
  start: mov ax, datasg
         mov ds, ax

         mov ax, stacksg
         mov ss, ax
         mov sp, 10H

         mov ax, 0B800H ; masm 汇编器要求立刻数不能以字母结尾
         mov es, ax

         mov bx, 0
         mov bp, 16

         mov cx, 3       ; 共写入 3 行
    s0:  mov si, 0
         mov di, 1824    ; di=1760+64, 1760 是 12 行第一字节的 offset, 每行两头地位的 offset=64
         add di, bx      ; 计算每一行开始写入的偏移地址
         mov ah, ds:[bp] ; 该行要显示的属性值

         push cx         ; 保留
         mov cx, 16
     s:  mov al, [si]
         mov es:[di], al ; 显存区域:字符低字节示意 ASCII
         inc di
         mov es:[di], ah ; 字符高字节对应色彩属性
         inc si
         inc di
         loop s

         add bx, 160 ; 0-160-320 (管制写入下一行)
         inc bp      ; 16-17-18(管制获取下一行的属性值)
         pop cx      ; 复原
         loop s0

         mov ax, 4c00H
         int 21H
codesg ends

end start

第十章

模块化程序设计

  1. callret 指令配合应用(近转移

    • call 等价于:push IP + jmp ...
    • ret 等价于:pop IP
  2. call 和 retf 指令配合应用(远转移

    • call 等价于:push CS + push IP + jmp ...
    • retf 等价于:pop IP + pop CS(留神这个程序)

call 指令

相当于 将 call 指令之后的那一个指令 IPCS+IP 压栈之后,进行 jmp 转移。
反对 近转移 远转移 ,不反对 短转移

  • call Label

    • push IP
    • jmp near ptr Label
  • call far ptr Label

    • push CS
    • push IP
    • jmp far ptr Label
  • call 16 位寄存器

    • push IP
    • jmp 16 位寄存器
  • call word ptr 内存地址

    • push IP
    • jmp word ptr 内存地址
  • call dword ptr 内存地址

    • push CS
    • push IP
    • jmp dword ptr 内存地址

总结——【目前曾经介绍的】转移指令对应的机器码

call 转移指令 机器码 jmp 转移指令 机器码
call L E8 ????(16 位位移量) jmp near ptr L E9 ????
call far ptr L 9A ???? ????<br/> 标号在段中的偏移地址 标号所在段地址 jmp far ptr L EA ???? ????
call ax、call bx FFD0、FFD3 jmp ax、jmp bx FFE0、FFE3
call word ptr addr FF160000 (todo) jmp word ptr addr FF260000 (todo)
call dword ptr addr FF1E0000 (todo) jmp dword ptr addr FF2E0000 (todo)

8086 中乘法的计算规定

汇编指令:mul 乘数(在内存或某个寄存器中),【被乘数和乘数】要么都是 8 位,要么都是 16 位

8 位乘数 16 位乘数
被乘数 8 位——在 al 16 位——在 ax
后果 ax dx 存高 16 位、ax 存低 16 位

试验十:编写子程序

(1)指定地位打印字符串

exp10_1.asm

(2)解决除法溢出的问题

exp10_2.asm

(3)二进制转十进制,打印

exp10_3.asm

退出移动版