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

大灰狼之四——第一个汇编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的内容表示字符属性不变。

最后程序执行结果如下:


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值