第四章 数据传送,寻址和算术运算

by admin on 2020年1月22日

lahf: 把eflag的低字节拷贝到ah,sahf相反
xchg 交流指令

全局变量在哪些地点定义?

本条顺序的骨干指标是:试验大地方的读写,在敬服情势上面寻址空间可达4GB,实格局下只可以寻址1MB。(why:为何珍重方式下能有那般大的寻址工夫,而实方式下极度?answer:实形式下有二十人的地址总线,保养情势下有三二十人地址总线)

交换val1和val2的值:
mov ax,val1
xchg val2,ax
mov  val1,ax

  .data和.data?

读写es段,5MB处的多寡。首先读出初阶处的8字节的源委,然后写入七个字符串,再从当中读出。

***************************************************************************
cpu实践减法的时候是对减数求补在相加

格式如下:

读写字符串,使用的是[es:edi]和[es:esi]

推断溢出:
2个整数相加得负数
2个负数相加的整数
结论:用位6xor位7的进位值设置of
  

  变量名 类型 初始值1,初始值2…

; ==========================================

算术指令:
inc,dec不设置cf
add,sub,neg取反,adc,sbb设置cf,of,zf,pf,sf

  变量名 类型 重复数
dup(初始值1,初始值2,…)

; pmtest2.asm

 

  变量名 类型 ?

; 编写翻译方法:nasm pmtest2.asm -o pmtest2.com

offset 取偏移地址
ptr重载变量的尺寸
type再次回到数组瓜时素的大小 单位字节
lengthof再次回到数组成分数目,只限大器晚成行。除例1
例1:

项目有怎么样?

; ==========================================

array byte 1,2,3,
               4
lenthof array   的值 为4

  字节 byte/db 字 word/dw 双字dword/dd 三字fword/df 四字qword/dq
十字节 tbyte/dt 有标记字节 sbyte 单精度浮点 real4

%include “pm.inc” ; 常量, 宏, 以至部分认证

***************************************************************************
array  byte 1,2,3
         byte 4
lengthof array  的值 为 3

  val db ? ;定义变量

org 0100h

***************************************************************************

  buffer dw 64
dup(0卡塔尔  ;定义陆拾二个字的缓冲区

jmp LABEL_BEGIN

sizeof再次来到数组大小,特殊情况同lengthof
sizeof = type * lengthof
label对同样变量定义新尺寸,无实际存款和储蓄空间
val16 label word
val32 dword 123456h

  szText db
‘abc123’,0dh,0ah  ;定义字符串 ASCII字符串加回车换行

[SECTION .gdt]

 

留意:定义字节和字在内部存款和储蓄器中贮存的不相同

; GDT

***************************************************************************
aligh 边界值 ;按边界值对齐
val1 byte ? 0040 0000
aligh 2
val2 word ? 0040 0002

  内部存储器以字为存款和储蓄单位,低位在前,高位在后;

;                            段基址,        段界限 , 属性

***************************************************************************

LIST

10   VAL 34H
LIST+1 20   VAL+1 12H
LIST+2 30   VAL+2 78H
LIST+3 40    VAL+3 56H

LABEL_GDT:        Descriptor    0,              0, 0        ; 空描述符

直白寻址:便是用变量名寻址
mov eax,val
直接寻址
mov eax,【esi】
指南针:包含地址的变量

list db 10,20,30,40

LABEL_DESC_NORMAL: Descriptor    0,        0ffffh, DA_DRW    ; Normal
描述符

变量名在数据段变量的开头消除释为 内部存款和储蓄器的地点
变量名在命令中的解释为 内部存储器的内容
array byte 1,2,3,4
ptrb dword array ;ptrb=offset array
mov al, array  ;al = 1

  mov al,list

LABEL_DESC_CODE32: Descriptor    0, SegCode32Len-1, DA_C+DA_32;
非大器晚成致代码段, 32

***************************************************************************

  mov bl,list+1

LABEL_DESC_CODE16: Descriptor    0,        0ffffh, DA_C      ;
非风流倜傥致代码段, 16

typedef 允许创设跟基本类型相同的自定义类型

  mov cl,list+2

LABEL_DESC_DATA:  Descriptor    0,      DataLen-1, DA_DRW    ;
Data

loop指令的实施:先减在比较,不为0才跳转
享有准则跳转指令的跳转范围 -128–127
在任何意况下 loopd 用ecx作为流速计 loopw用cx作为计数器

  mov dl,list+3

LABEL_DESC_STACK:  Descriptor    0,    TopOfStack, DA_DRWA+DA_32;
Stack, 32 位

val dw 1234h,5678h

LABEL_DESC_TEST:  Descriptor 0500000h,    0ffffh, DA_DRW

  mov ax,val      ;ax=1234h 

LABEL_DESC_VIDEO:  Descriptor  0B8000h,    0ffffh, DA_DEscortW    ;
显存首地址

  mov bx,val+2

; GDT 结束

  mov dx,word ptr val+1

GdtLen equ $ – LABEL_GDT ; GDT长度

  mov eax,dword ptr val

GdtPtr dw GdtLen – 1 ; GDT界限

疑问?

dd 0 ; GDT基地址

 图片 1

; GDT 选择子

注:单引号和双引号的差别,能够互相定义对应的字符,比如:
“aaa’a'” -> 输出结果:aaa’a’

SelectorNormal equ LABEL_DESC_NORMAL – LABEL_GDT

‘aaa”a”‘ -> 输出结果:aaa”a”

SelectorCode32 equ LABEL_DESC_CODE32 – LABEL_GDT

 

SelectorCode16 equ LABEL_DESC_CODE16 – LABEL_GDT

生龙活虎对变量 

SelectorData equ LABEL_DESC_DATA – LABEL_GDT

  成效域在单个子程序,归于货仓变量,伪指令 LOCAL

SelectorStack equ LABEL_DESC_STACK – LABEL_GDT

  LOCAL 变量名1[重新数量]:[类型],…

SelectorTest equ LABEL_DESC_TEST – LABEL_GDT

  test proc

SelectorVideo equ LABEL_DESC_VIDEO – LABEL_GDT

    LOCAL @val:dword      ;@定义一个某个变量,便于区分,

; END of [SECTION .gdt]

    LOCAL @buffer[1024]:btye

[SECTION .data1] ; 数据段

    LOCAL @wnd:WNDCLASS  ;定义三个WNDCLASS数据构造

ALIGN 32

    mov eax,0FFFFFFFFH

[BITS 32]

    mov @val,eax

LABEL_DATA:

  test endp 

SPValueInRealMode dw 0

; 字符串

PMMessage: db “In Protect Mode now. ^-^”, 0 ; 在保养方式中显示

OffsetPMMessage equ PMMessage – $$

StrTest: db “ABCDEFGHIJKLMNOPQRSTUVWXYZ”, 0

OffsetStrTest equ StrTest – $$

DataLen equ $ – LABEL_DATA

; END of [SECTION .data1]

; 全局仓库段

[SECTION .gs]

ALIGN 32

[BITS 32]

LABEL_STACK:

        times 512 db 0

        TopOfStack equ $ – LABEL_STACK – 1

; END of [SECTION .gs]

[SECTION .s16]

[BITS 16]

LABEL_BEGIN:

        mov ax, cs

        mov ds, ax

        mov es, ax

        mov ss, ax

        mov sp, 0100h

        mov [LABEL_GO_BACK_TO_REAL+3], ax  
将LABEL_GO_BACK_TO_REAL中的jmp指令的第八个字节校正位cs_real_mode值,实现jmp准确的跳转

        mov [SPValueInRealMode], sp

        ; 开端化 16 位代码段描述符

        mov ax, cs

        movzx eax, ax

        shl eax, 4

        add eax, LABEL_SEG_CODE16

        mov word [LABEL_DESC_CODE16 + 2], ax

        shr eax, 16

        mov byte [LABEL_DESC_CODE16 + 4], al

        mov byte [LABEL_DESC_CODE16 + 7], ah

        ; 开端化 32 位代码段描述符

        xor eax, eax

        mov ax, cs

        shl eax, 4

        add eax, LABEL_SEG_CODE32

        mov word [LABEL_DESC_CODE32 + 2], ax

        shr eax, 16

        mov byte [LABEL_DESC_CODE32 + 4], al

        mov byte [LABEL_DESC_CODE32 + 7], ah

        ; 起初化数据段描述符

        xor eax, eax

        mov ax, ds

        shl eax, 4

        add eax, LABEL_DATA

        mov word [LABEL_DESC_DATA + 2], ax

        shr eax, 16

        mov byte [LABEL_DESC_DATA + 4], al

        mov byte [LABEL_DESC_DATA + 7], ah

        ; 早先化旅社段描述符

        xor eax, eax

        mov ax, ds

        shl eax, 4

        add eax, LABEL_STACK

        mov word [LABEL_DESC_STACK + 2], ax

        shr eax, 16

        mov byte [LABEL_DESC_STACK + 4], al

        mov byte [LABEL_DESC_STACK + 7], ah

        ; 为加载 GDTR 作准备

        xor eax, eax

        mov ax, ds

        shl eax, 4

        add eax, LABEL_GDT ; eax <- gdt 基地址

        mov dword [GdtPtr + 2], eax ; [GdtPtr + 2] <- gdt 基地址

        ; 加载 GDTR

        lgdt [GdtPtr]

        ; 关中断

        cli

        ; 打开地址线A20

        in al, 92h

        or al, 00000010b

        out 92h, al

        ; 准备切换成保护形式

        mov eax, cr0

        or eax, 1

        mov cr0, eax

        ; 真正步向敬性格很顽强在荆棘满途或巨大压力面前不屈情势

        jmp dword SelectorCode32:0 ; 实行这一句会把 SelectorCode32 装入
cs, 并跳转到 Code32Selector:0  处

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

LABEL_REAL_ENT奥德赛Y: ; 从珍重情势跳回到实方式就到了此处

        mov ax, cs

        mov ds, ax

        mov es, ax

        mov ss, ax

        mov sp, [SPValueInRealMode]

        in al, 92h ; `.

        and al, 11111101b ;  | 关闭 A20 地址线

        out 92h, al ; /

        sti ; 开中断

        mov ax, 4c00h ; `.

        int 21h ; /  回到 DOS

 ; END of [SECTION .s16]

[SECTION .s32]; 32 位代码段. 由实情势跳入.

[BITS 32]

LABEL_SEG_CODE32:

        mov ax, SelectorData

        mov ds, ax ; 数据段选取子

        mov ax, SelectorTest

        mov es, ax ; 测验段接纳子

        mov ax, SelectorVideo

        mov gs, ax ; 摄像段选取子

        mov ax, SelectorStack

        mov ss, ax ; 货仓段接收子

        mov esp, TopOfStack

        ; 上面展现二个字符串

        mov ah, 0Ch ; 0000: 黑底    1100: 红字

        xor esi, esi

        xor edi, edi

        mov esi, OffsetPMMessage ; 源数据偏移

        mov edi, (80 * 10 + 0) * 2 ; 目标数目偏移。荧屏第 10 行, 第 0
列。

        cld  将数据从esi拷贝到edi

.1:

        lodsb

        test al, al 测量试验al是不是为空

        jz .2

        mov [gs:edi], ax

        add edi, 2

        jmp .1

.2: ; 展现实现

        call DispReturn

        call TestRead

        call TestWrite

        call TestRead

        ; 到此下马

        jmp SelectorCode16:0

;

TestRead:     将[es:esi]中的数据各个以16进制格局显得出来

        xor esi, esi

        mov ecx, 8

.loop:

        mov al, [es:esi]

        call DispAL

        inc esi

        loop .loop

        call DispReturn

        ret

; TestRead
结束———————————————————–

;

TestWrite:   OffsetStrTest的数额写入到[es:edi]

        push esi

        push edi

        xor esi, esi

        xor edi, edi

        mov esi, OffsetStrTest ; 源数据偏移

        cld

.1:

        lodsb

        test al, al 

        jz .2      测验贮存器al是不是为空,即便为空,则跳转2

        mov [es:edi], al    

        inc edi

        jmp .1

.2:

        pop edi

        pop esi

        ret

; TestWrite
结束———————————————————-

;

; 彰显 AL 中的数字

; 默认地:

; 数字已经存在 AL 中

; edi 始终照准要体现的下三个字符之处

; 被更改的贮存器:

; ax, edi

;

DispAL: 将al中的字节用16进制方式展现出来

        push ecx

        push edx

        mov ah, 0Ch ; 0000: 黑底    1100: 红字

        mov dl, al

        shr al, 4

        mov ecx, 2

.begin:

        and al, 01111b

        cmp al, 9

        ja .1

        add al, ‘0’

        jmp .2

.1:

        sub al, 0Ah

        add al, ‘A’

.2:

        mov [gs:edi], ax

        add edi, 2

        mov al, dl

        loop .begin

        add edi, 2

        pop edx

        pop ecx

        ret

; DispAL
结束————————————————————-

;

DispReturn: 更正的edi的值,让下二个字符呈现在下意气风发行的伊始处

        push eax

        push ebx 

        mov eax, edi

        mov bl, 160

        div bl

        and eax, 0FFh

        inc eax

        mov bl, 160

        mul bl

        mov edi, eax

        pop ebx

        pop eax

         ret

; DispReturn
结束———————————————————

SegCode32Len equ $ – LABEL_SEG_CODE32

; END of [SECTION .s32]

; 16 位代码段. 由 32 位代码段跳入, 跳出后到实情势

[SECTION .s16code]

ALIGN 32

[BITS 16]

LABEL_SEG_CODE16:

        ; 跳回实形式:

        mov ax, SelectorNormal

        mov ds, ax

        mov es, ax

        mov fs, ax

        mov gs, ax

        mov ss, ax 

        mov eax, cr0

        and al, 11111110b

        mov cr0, eax

LABEL_GO_BACK_TO_REAL:

        jmp 0:LABEL_REAL_ENTENVISIONY ; 段地址会在程序开始处被设置成无误的值

Code16Len equ $ – LABEL_SEG_CODE16

; END of [SECTION .s16code]

大器晚成、cld汇编指令

与cld相对应的命令是std,二者均是用来操作方向标记位DF(Direction
Flag)。cld使DF
重新载入参数,正是让DF=0,std使DF置位,即DF=1.那五个指令用于串操作指令中。通过奉行cld或std指令能够决定方向标记DF,决定内部存款和储蓄器地址是外加(DF=0,向高地址增添)依旧收缩(DF=1,向地地址减小)。

源操作数和指标操作数分别采纳存放器(e卡塔尔(قطر‎si和(e卡塔尔国di进行直接寻址;每实行一遍串操作,源指针(e卡塔尔(قطر‎si和目标指针(e卡塔尔国di将自行举办退换:±1、±2、±4,其相应的分别是字节操作、字操作和双字操作。

在进行该指令早先,必须预置SI和DI的初值,用STD或CLD设置DF值.

MOVS DST , SRC
//同上,临时用,DST和SRC只是用来用类型检查,并不准使用其余寻址形式来明确操作数.

        1.指标串必得在附加段中,即必得是ES:[DI]

        2.源串同意使用段赶过前缀来修饰,但偏移地址必需是[SI].

二、lodsb 字符串操作指令

汇编语言中,串操作指令LODSB/LODSW是块装入指令,其具体操作是把SI指向的存款和储蓄单元读入累计器,LODSB就读入AL,LODSW就读入AX中,然后SI自动扩展或减小1或2.其平时是对数组或字符串中的成分各种进行管理。

三、test汇编指令

test归属逻辑运算指令

效果: 实行BIT与BIT之间的逻辑运算

测量检验(两操作数作与运算,仅修正标记位,不回送结果卡塔尔.

Test对五个参数(目的,源State of Qatar实践AND逻辑操作,并依靠结果设置标记存放器,结果作者不会保留。TEST
AX,BX 与 AND AX,BX 命令有相符效果

语法: TEST r/m,r/m/data

影响标记: C,O,P,Z,S(个中C与O八个标识会被设为0卡塔尔国

图片 2

四、div指令

图片 3

五、loop指令

loop指令的格式是:loop标号,cpu试行loop指令的时候,要开展两步操作

1.(cx)=(cx)-1

2.剖断cx中的值,不为零则转至标号处推行,就算为零,则向下执行

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图