您的位置:首页 > 其它

大灰狼笔记四-汇编hello,world

2013-03-19 22:03 337 查看
大灰狼之四——第一个汇编hello,world

先来看一段C的hello,world实现

char msg[]="hello,world";
int main(int argc, char *argv)
{
printf("%s\n",msg);
return 0;
}

其中msg是全局变量,存放在数据段中,而printf是执行代码,存放在代码段中。

而汇编语言并不知道汇编代码所对应的数据应该存放在哪个段中,因此使用assume来定义:

assume:表示用来假设某一段寄存器和程序中的某一个用segment~ends所定义的代码相关连。

而要定义数据的内容,相当与给上述代码中的全局变量msg赋值,则应该用db(defined byte)指令:lable db initializer

其中lable是标号,相当与变量名,而initializer则是变量的初始值。因此,汇编中的赋值语句为:msg db “hello,world”

而定义了数据之后,如何实现printf函数的功能,也就是将字符串显示到屏幕上呢?

由这一点引出了print函数的本质,也就是CPU内存地址间的交互。CPU为了方便和其他设备进行更加快速的交互,将CPU内部的内存进行了分段,分段如下:



因此我们需要将字符的内容copy到显存中,,则屏幕就会显示显存中的内容,这也就是printf函数的本质。

内存中的具体地址分配如下:



其中A0000-BFFFF中有多种显示模式,而我们需要用到的是VGA显存空间,也就是80*25的彩色字符模式,在显存中的位置是B8000H-BFFFF共32k的地址,只要向该地址写入数据,内容便会立刻显示至屏幕。

而针对每一个单独的字符,则需要占据16位,8位用于表示字符的ASCII码,剩下8位用于表示字符的属性。

属性表示如下:



显卡的缓存共分8页,每页有4kb,可显示任意一页的内容,但一般显示第0页,即B8000H-B8900H

因此,汇编hello,world的代码如下:

ASSUME CS:CODE,DS:DATA

DATA SEGMENT
MSG DB "hello,world"
DATA ENDS

CODE SEGMENT
START:
MOV AX,DATA
MOV DS,AX
MOV CX,11
MOV BX,0B800H
MOV ES,BX
MOV SI,0
MOV BX,0
MOV AH,01000010B
S:MOV AL,DS:[SI]
MOV ES:[BX],AL
MOV ES:[BX+1],AH
INC SI
ADD BX,2
LOOP S
MOV AH,4CH
INT 21H
CODE ENDS
END START
其中db是define byte,也就定义了字节的内容。start后跟的语句首先将数据段的地址赋给DS寄存器。

初始化CX寄存器,作为循环变量。

BX的内容是上文提到的需要写入的显存的地址。

AH是所显示字符的属性。

接下来的S loop也就是将数据段中定义的字符一个一个送到显示器上进行显示。其中BX需要加2是因为一个字符由于还有其属性,占据了两个byte。另外,AH的内容表示字符属性不变。

最后程序执行结果如下:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: