首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

(汇编初级有关问题)请教这里是用什么命令输出的

2012-11-09 
(汇编初级问题)请问这里是用什么命令输出的之前只知道调用bios中断10h和dos中断21h,然后读取相应的寄存器

(汇编初级问题)请问这里是用什么命令输出的
之前只知道调用bios中断10h和dos中断21h,然后读取相应的寄存器数据,来输出内容。

这里的TestRead-》DispAL里面调用的哪个命令是屏幕输出呢? 是怎么输出的呢?

哪些文章或书是有关这些I/O一类方面的?

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

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


%include "pm.inc" ; 常量, 宏, 以及一些说明 


org 0100h 
jmp LABEL_BEGIN 


[SECTION .gdt] 
; GDT 
; 段基址, 段界限 , 属性 
LABEL_GDT: Descriptor 0, 0, 0 ; 空描述符 
LABEL_DESC_NORMAL: Descriptor 0, 0ffffh, DA_DRW ; Normal 描述符 
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len - 1, DA_C + DA_32 ; 非一致代码段, 32 
LABEL_DESC_CODE16: Descriptor 0, 0ffffh, DA_C ; 非一致代码段, 16 
LABEL_DESC_DATA: Descriptor 0, DataLen - 1, DA_DRW ; Data 
LABEL_DESC_STACK: Descriptor 0, TopOfStack, DA_DRWA + DA_32 ; Stack, 32 位 
LABEL_DESC_TEST: Descriptor 0500000h, 0ffffh, DA_DRW 
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址 
; GDT 结束 


GdtLen equ $ - LABEL_GDT ; GDT长度 
GdtPtr dw GdtLen - 1 ; GDT界限 
dd 0 ; GDT基地址 


; GDT 选择子 
SelectorNormal equ LABEL_DESC_NORMAL - LABEL_GDT 
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT 
SelectorCode16 equ LABEL_DESC_CODE16 - LABEL_GDT 
SelectorData equ LABEL_DESC_DATA - LABEL_GDT 
SelectorStack equ LABEL_DESC_STACK - LABEL_GDT 
SelectorTest equ LABEL_DESC_TEST - LABEL_GDT 
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT 
; END of [SECTION .gdt] 


[SECTION .data1] ; 数据段 
ALIGN 32 
[BITS 32] 
LABEL_DATA: 
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 
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_ENTRY: ; 从保护模式跳回到实模式就到了这里 
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, 0Bh ; 0000: 黑底 1100: 红字 
xor esi, esi 
xor edi, edi 
mov esi, OffsetPMMessage ; 源数据偏移 
mov edi, (80 * 10 + 0) * 2 ; 目的数据偏移。屏幕第 10 行, 第 0 列。 
cld 
.1: 
lodsb 
test 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: 
xor esi, esi 
mov ecx, 8 
.loop 
mov al, [es:esi] 
call DispAL 
inc esi 
loop .loop 


call DispReturn 


ret 
; TestRead 结束----------------------- 




; ------------------------------------ 
TestWrite: 
push esi 
push edi 
xor esi, esi 
xor edi, edi 
mov esi, OffsetStrTest ; 源数据偏移 
cld 
.1: 
lodsb 
test al, al 
jz .2 
mov [es:edi], al 
inc edi 
jmp .1 
.2: 


pop edi 
pop esi 


ret 
; TestWrite 结束---------------------- 




; ------------------------------------ 
; 显示 AL 中的数字 
; 默认地: 
; 数字已经存在 AL 中 
; edi 始终指向要显示的下一个字符的位置 
; 被改变的寄存器: 
; ax, edi 
; ------------------------------------ 
DispAL: 
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: 
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_ENTRY ; 段地址会在程序开始处被设置成正确的值 


Code16Len equ $ - LABEL_SEG_CODE16 


; END of [SECTION .s16code]

[解决办法]
mov [gs:edi], ax

直接写屏幕缓存,你可以看一下他前面怎么初始化的,第10行第0列等等。
[解决办法]
还不明白么?我再说的详细点:

1 LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; 显存首地址 
初始化显存选择子结构

2 mov ax, SelectorVideo
mov gs, ax ; 视频段选择子
将上面init的选择子装入gs段寄存器,so以后通过gs访问显存。

3 mov [gs:edi], ax 
实际写入显存

热点排行