zoukankan      html  css  js  c++  java
  • 《汇编语言》(王爽)补充笔记,第 1 ~ 9 章

    第一章

    ● CPU 地址总线决定寻址能力,数据总线决定数据传输时一次数据传送量,控制总决定对系统中其他设备的控制能力

    第二章 寄存器(以 16 位 8086 CPU 进行讨论)

    ● 内部总线用于链接 CPU 内各器件,外部总线用于连接 CPU 与其他器件

    ● 8086 CPU 的寄存器:AX,BX,CX,DX,SI,DI,SP,BP,IP,CS,SS,DS,ES,PSW

    ● 物理地址 = 段地址 *16 + 偏移地址,即(十六进制)段地址左移一位,加上偏移地址,记作 “段地址 : 偏移地址” 或 “SA : EA”。这决定了每个内存段起点地址一定是 16 的倍数(十进制视角),切每个段的最大长度为 64 KB(偏移地址 4 位,寻址 2^16 Byte)。由于段地址在和偏移地址均有 4 位,每个物理地址可以由不同的段地址和偏移地址组合而成。

    ● CS 是 代码段寄存器,IP 是指令指针寄存器,任意时刻,CPU 将从 CS *16 + IP 的地址读取下一条指令来执行,用 CS:IP 来表示。

    ● 当新指令被加载到指令缓冲期中时,IP 的值根据新指令的长度(1 ~ 7 Byte)自增相应字节,自动指向下一条指令。

    ● 8086 CPU 加电启动或复位后,CS 初始化为 FFFFh,IP 初始化为 0000h。

    ● 能够改变 CS 或 IP 的指令称为转移指令。可以用 “jmp 段地址 : 偏移地址” 来一次性修改 CS 和 IP,也可以用 “jmp reg” 来单修改 IP。

    ● Debug 模式中的命令:

      R:查看、改变寄存器的内容

      D:查看内存内容

      E:改写内存内容

      U:将内存中的机器指令翻译为汇编指令

      T:执行一条机器指令

      A:以汇编指令的格式在内存中写入一条机器指令

      P:自动重复执行循环直到 cx == 0

    第三章 内存访问

    ● 字单元,即存放一个字类型数据的内存单元,分为高位字节和地位字节

    ● 指令 “mov al, [imm]” 或 “mov [imm], al” 中内存单元是段地址 ds,偏移地址 imm

    ● 8086 CPU 不支持直接将数据送入段寄存器 ds,只能用一个通用寄存器作中介

    ● 8086 CPU 栈操作以字为单位(与通用寄存器等宽),任何时刻,SS : SP 指向栈顶元素,进出栈用 SP ±2h 来移动,一个栈段容量最大为 64 KB(SP = 0000h ~ FFFFh)

    ● 系统不自动检测栈操作越界行为,即不记录当前栈空间大小

    ● push 和 pop 指令也可以对段寄存器和内存单元使用

    第四章 第一个程序

    ● 代码,示例程序,使用教材自带的 masm.exe 和 link.exe 进行编译和连接,由操作系统程序 command.com 加载,最后由 CPU 逐条执行。

     1 ; tt.asm
     2 assume cs: codesg  ; 伪指令 assume 做段标记,程序加载时寄存器指向位置,见第六章说明
     3 
     4 codesg segment    ; 名为 codesg 的段
     5     mov ax, 0123h
     6     mov bx, 0456h
     7     add ax, bx
     8     add ax, ax
     9 
    10     mov ax, 4C00h  ; 与程序返回值相关
    11     int 21h
    12 
    13 codesg ends
    14 
    15 end

    ■ dosbox 中的操作

    ■ 编译结果(tt_masm.lstw 文件部分)

     1                                                              Page     1-1
     2 
     3 
     4                 assume cs: codesg 
     5                  
     6  0000                codesg segment 
     7  0000  B8 0123                mov ax, 0123h  ; 依次为指令偏移量,机器指令,汇编指令
     8  0003  BB 0456                mov bx, 0456h 
     9  0006  03 C3                add ax, bx 
    10  0008  03 C0                add ax, ax 
    11                  
    12  000A  B8 4C00                mov ax, 4C00h 
    13  000D  CD 21                int 21h 
    14                  
    15  000F                codesg ends 
    16                  
    17                 end 

    ■ 使用 debug 查看。CX为程序长度;DS : 0000h 指向程序内存地址,该区前 256 字节存放程序段前缀数据区(PSP)用于与 DOS 操作系统通信。CS = DS + 10h,CS : IP 指向程序首指令的内存地址。

    第五章 [ ] 与 loop 指令

    ● [ ] 的用法

      mov al,[imm]           单独中括号中的立即数,被解释为立即数本身

      mov al, reg : [imm]  有段地址前缀中括号中的立即数,被解释为内存 reg : imm 处的值。这里 reg 称为段前缀

      mov al, [reg]            单独中括号中的寄存器,解释为内存中段地址 ds,偏移地址 reg 处的值

    ● DOS 与其他合法程序一般不使用 0 : 0200h ~ 0 : 02FFh 这 256 Byte 的内存空间,若该范围内容全为 0,则表示没有程序在使用这段内存。

    第六章 包含多个段的程序

    ● 程序开头使用 dw 来定义一些字类型的数据(dw 是 define word 的意思,而不是 double word),在程序加载后以 CS : 0000h 指向,范例代码:

    assume cs:code
    
    code segment
        dw 0123h, 0456h, 0789h, 0abch, 0defh, 0fedh, 0cbah, 0987h
    
    start:        ; 标记程序入口点
        mov bx, 0
        mov ax, 0
        mov cx, 8
    s:
        add ax, cs:[bx]
        add bx, 2
        loop s
        
        mov ax, 4c00h
        int 21h
    code ends
    
    end start      ; 指定程序入口点

    ■ debug 中的结果,第一行 CS : 0000 为数据,第二行 CS : IP 开始为指令

    ● 代码,手工申请和维护一段内存空间用作栈

     1 assume cs:codesg
     2 
     3 codesg segment
     4     dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
     5     dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0   ; 16个字的空间用作栈             
     6 
     7 start:                  ; 数据和指令在一个内存段中,没有分开
     8     mov ax, cs       
     9     mov ss, ax      ; 注意 debug -t 时该指令会与下一条指令同时执行
    10     mov sp, 30h       
    11 
    12     mov bx, 0       ; 当前数据偏移地址
    13     mov cx, 8
    14 s0:
    15     push cs:[bx]    ; 取数据压栈
    16     add bx, 2       ; 指向下一个数据
    17     loop s0         ; 以上将代码段0~15单元中的8个字型数据依次入栈
    18 
    19     mov bx, 0
    20     mov cx, 8
    21 s1:
    22     pop cs:[bx]     ; 依次出栈
    23     add bx, 2
    24     loop s1
    25     
    26     mov ax, 4c00h
    27     int 21h
    28 codesg ends
    29 
    30 end start

    ● 代码,程序中自定义多个内存段

     1 assume cs:code, ds:data, ss:stack   ; 程序加载时三个寄存器分别指向各个内存段
     2 
     3 data segment
     4   dw 0123H, 0456H, 0789H, 0abcH, 0defH, 0fedH, 0cbaH, 0987H
     5 data ends
     6 
     7 stack segment
     8   dw 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
     9 stack ends
    10 
    11 code segment
    12 start:
    13     mov ax, stack   ; 直接使用内存段的名字作为其地址
    14     mov ss, ax
    15     mov sp, 20h
    16     
    17     mov ax, data
    18     mov ds, ax        
    19     
    20 ;   ...             ; 中间过程,省略
    21 
    22     mov ax, 4c00h
    23     int 21h
    24 code ends
    25 
    26 end start

    第七章 更灵活的定位内存地址的方法

    ● 书中 [reg1 + reg2 / imm] 表示内存地址 (ds) * 16 + (reg1) + (reg2) / imm 处的值

    ● ASCII 大写改小写:or al, 11111111b 或 or al, FFh;小写改大写:and al, 11011111b 或 and al, DFh;

    ● 寄存器 SI 和 DI 不能拆分为高低字节来使用

    第八章 数据处理的两个基本问题

    ● 8086 CPU 寄存器只有 bx,si,di 和 bp 可以用于 [...] 寻址;以单个或 bx / bp + si / di 的形式出现,不能出现诸如 [bx + bp]、[si + di] 等;bx 寻址默认段地址为 ds,bp 寻址默认段地址为 ss

    ● 机器指令层面仅关心志林执行前一刻数据所在的位置,包括 CPU内部、内存和端口

    ● 没有寄存器参与的内存访问和运算指令中,用 PTR 指定数据类型很有必要,除非指令已经先定了操作数类型(如 push 以字类型执行)

    第九章 转移指令的原理

    ● 8086 CPU 转移指令分类为:无条件转移,条件转移,循环,过程,中断

    ● 只修改 IP 的转移指令称为段内转移(分短转移 -128 ~ +127 和近转移 -32768 ~ +32767),同时修改 CS 和 IP 的转移指令称为段间转移。

    ● jmp 指令执行时没有记录目的地址,而记录跳转偏移量,并以此调整 IP,达到跳转目的。向后转移时编译器会先在 jmp后预留 nop 指令,以便找到跳转目标后再填充,用不完的 nop 留在原地

    ● jmp short mark 实现段内短转移,执行本质是 IP += (mark 地址) - (jmp 指令最后字节地址),编译时计算,机器码为 EBXX(XX为有符号字节数)

    ● jmp near PTR mark 实现段内近转移,本质同上,将范围扩大了而已,机器码为 E9XXXX

     1 assume cs:code
     2 
     3 code segment
     4 start:
     5     mov ax, 5h    
     6     jmp short s
     7     add ax, 1h
     8     ;mov bx, 6h      ; 第一个程序注释掉,第二个程序再恢复
     9 s:
    10     sub ax, 1h
    11 
    12     mov ax, 4c00h
    13     int 21h
    14 code ends
    15 
    16 end start

    ● jmp far PTR mark 实现段间转移(远转移),执行本质是 CS = (mark 段地址),IP = (mark 偏移地址),就是精确地跳转到 mark 所在地址(不用额外计算任何数值),机器码为EAXXXXXXXX

     1 assume cs:code
     2 
     3 code segment
     4 start:
     5     mov ax, 5h    
     6     jmp far ptr s
     7     db 256 dup(0)   ; 插入远大于段内跳转最大长度的指令    
     8 s:
     9     sub ax, 1h
    10 
    11     mov ax, 4c00h
    12     int 21h
    13 code ends
    14 
    15 end start

    ● jmp word PTR [addr] 实现段内转移,addr 为各种寻址方式的内存地址,用作跳转的偏移地址

    ● jmp dword PTR [addr] 实现段间转移,addr 的高字用作跳转段地址(CS = [addr + 2]),低字用作跳转偏移地址(IP = [addr])

    ● 指令 jcxz(cx 等于零跳转)和 loop 都是利用寄存器 cx 的值进行条件跳转

    ● 形如 jmp imm1 : imm2 的指令是在 debug 程序中手动跳转内存显示用的, 不能用在源程序中

  • 相关阅读:
    20155315 2016-2017-2 《Java程序设计》第二周学习总结
    20155315 2016-2017-2 《Java程序设计》第一周学习总结
    20155315庄艺霖第三次作业之Linux初体验
    20155315庄艺霖--对做中学的理解及对c语言和Java的看法
    20165330 实验一 Java开发环境的熟悉
    20165330 2017-2018-2 《Java程序设计》第5周学习总结
    20165330 2017-2018-2 《Java程序设计》第4周学习总结
    第四周课堂实践总结
    20165330 2017-2018-2 《Java程序设计》第3周学习总结
    20165330 2017-2018-2 《Java程序设计》第2周学习总结
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/9655247.html
Copyright © 2011-2022 走看看