x86汇编语言之字符串和函数的定义以及变量的取值赋值

2,218 阅读3分钟

「这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

x86汇编语法

  1. 注释
;我是注释
  1. 变量取值和赋值(传送指令)
;赋值
mov ax,2000H ;将十六进制2000赋值给十六位寄存器ax  相当于ax=2000H


;取值
mov bx,ax ;将ax中的值取出赋值给bx  相当于bx=ax

存放的数据大小根据使用的寄存器而定, 比如ax是16位寄存器,最大只能存放16位数据,也就是4位十六进制数据

十六进制数据不能以字母开头, 前面需加上0 否则编译报错

  1. 函数声明

结构如下:

函数名:
	函数体
	ret   ;结尾标记

示例:

print:	;函数名
		mov dx,offset str
		mov ah, 9ch 
		int 21h
		
		ret ;函数结尾标记
  1. 函数调用

x86架构中使用关键指令call

x86架构汇编示例:

		call print ;调用print函数
		
		;退出程序
		mov ah, 4ch 
		int 21h
		
print:	;函数名
		mov dx,offset str;获取别名对应数据的偏移地址
		mov ah, 9ch ;9h表示调用显存 从dx总读取偏移地址对应的数据
		int 21h
		ret
  1. 字符串的定义

    起因:如果直接将字符串赋值给通用寄存器,会出现以下两个问题:

    • 字符顺序是反着的
    • 最多只能存放两个字符
    • 无法获取到数据地址,不能堆字符串进行修改

    为了解决这个问题,需要使用另外一种方式,定义字符串

    首先:需要先在内存中申请一块空间,可以使用伪指令dbdw

       db-->define byte  定义字节 读写一个数据,偏移量加1
       dw-->define word  定义字   读写一个数据,偏移量加2
           
           
       dd-->define double word 定义双字, 读写一个数据 偏移量加4
    
    • 示例

      db 'hello'  ;占用五个字节的内存空间
      dw 'hello'  ;占用六个字节的内存空间  跟偏移量有关系
      

    如果定义数字,使用dw每个数字占用两个字节的空间, 字符串比较特殊,并不是每个字符占用两个字节,而是总长度必须是2的倍数

  2. 字符串的获取

    获取字符串的数据,首先要获取到数据所对应的内存地址

    那怎么获取已经定义好的地址呢?

    第一步尝试: 给数据添加别名

    str db 'hello'
    
    start:
    	mov bx,str ;别名中存放的是偏移地址
    
    
    end start
    

    别名中存放的是偏移地址,但是光有偏移地址还不行,还需要段地址, 段地址+偏移地址=实际物理地址,别名默认从ds寄存器中读取段地址, 但是我们并没有给ds寄存器赋过值, 这就导致我们无法获取正确的数据,因为我们不知道正确的段地址是多少?

    那字符串段地址从哪里获取呢?

    • 方法一: 直接从内存中找(仅限于调试,实际开发肯定不行)

    • 方法二:使用段进行包裹, 段能给我们提供一个段地址(正解)

      data segment
      	str db 'hello'
      data ends
      	;使用段进行包裹, 可以借助段名称获取段地址
      start:
      	mov ax,data
      	mov ds,ax
      	mov bx,str 
      
      end start