汇编:语法速通

文章目录

HelloWorld

代码

复制代码
section  .text		;代码段起始
   global _start     ;导出_start符号到目标文件符号表,给链接器使用
   
_start:              ;入口地址
   mov   edx,len     ;长度立即数放入edx
   mov   ecx,msg     ;字符串地址放入ecx
   mov   ebx,1       ;准备使用stdout输出
   mov   eax,4       ;sys_write系统调用号
   int   0x80        ;触发软中断,内核根据eax调用sys_write,根据ebx写到stdout输出,内容为字符串地址后len长度的字节。
   
   mov   eax,1       ;内核返回后eax存放实际写入的字节数14,已经没用了,所以用1覆盖,准备调用sys_exit
   int   0x80        ;调内核终止进程

section  .data		;数据段起始
msg db 'Hello, world!', 0xa  ;声明msg变量,db表示define byte,按字节定义以下内容:字符串、0xa换行
len equ $ - msg     ;msg长度计算,等于地址之差

编译脚本

复制代码
#!/bin/bash

nasm -f elf hello.asm
ld -m elf_i386 -s -o hello hello.o
./hello

int 0x80 寄存器约定

寄存器 用途 对应参数
eax 系统调用号 4 = sys_write
ebx 第 1 个参数 文件描述符 fd
ecx 第 2 个参数 缓冲区地址 buf
edx 第 3 个参数 字节数 count

变量定义

伪指令 位数 典型用途
db 8 bit 字节串、ASCII 字符串
dw 16 bit 字、Unicode 字符
dd 32 bit 双字、32 位整数/地址
dq 64 bit 四字、64 位整数
dt 80 bit 扩展精度浮点(BCD)

equ用法

equ 是等值宏,类似C的 #define,在编译时原地替换为立即数,不占运行时内存。

如果想把 len 定义为变量,可以使用dd定义32位整数。

复制代码
len dd 14

代码段相应修改,表示取 len 内容放入edx。

复制代码
mov   edx,[len]

字符串数值比较

复制代码
section .text
   global _start         ;must be declared for using gcc

_start:                  ;tell linker entry point
   mov   ecx, [num1]    ;num1先放到ecx
   cmp   ecx, [num2]    ;比较num1>num2则跳转到check_third_num比较num1和num3,否则用num2放到ecx
   jg    check_third_num
   mov   ecx, [num2]
   
check_third_num:
   cmp   ecx, [num3]    ;比较ecx>num3则直接跳转到_exit,否则用num3放到ecx.
   jg    _exit
   mov   ecx, [num3]
   
_exit:
   mov   [largest], ecx    ;保证ecx中一定是最大值,mov到largest变量中。
   mov   ecx,msg    ;输出msg
   mov   edx, len
   mov   ebx,1  ;file descriptor (stdout)
   mov   eax,4  ;system call number (sys_write)
   int   0x80   ;call kernel
        
   mov   ecx,largest    ;输出最大值
   mov   edx, 2
   mov   ebx,1  ;file descriptor (stdout)
   mov   eax,4  ;system call number (sys_write)
   int   0x80   ;call kernel
    
   mov   eax, 1
   int   80h

section .data
   
   msg db "The largest digit is: ", 0xA,0xD 
   len equ $- msg 
   num1 dd 47
   num2 dd 22
   num3 dd 31

segment .bss
   largest resb 2  

循环打印0-9

复制代码
section .text
   global _start        ;must be declared for using gcc
        
_start:                 ;tell linker entry point
   mov ecx,10    ;循环次数
   mov eax, '0'    ;起始字符
        
l1:
   mov [num], eax
   mov eax, 4
   mov ebx, 1
   push ecx    ;循环计数器值入栈防止被破坏
        
   mov ecx, num    ;打印字符        
   mov edx, 1        
   int 0x80
        
   mov eax, [num]    ;取回打印后的字符
   sub eax, '0'    ;字符转数字'1' - '0' = 1
   inc eax        ;数字自增1
   add eax, '0'    ;数字转字符
   pop ecx    ;恢复循环计数器
   loop l1    ;ecx-- 不等于0时跳回l1(loop指令假定ecx包含循环计数值,直至减为0停止)
        
   mov eax,1             ;system call number (sys_exit)
   int 0x80              ;call kernel
section .bss
	num resb 1

求和函数(过程)

复制代码
section .text
   global _start        ;must be declared for using gcc
        
_start:                 ;tell linker entry point
   mov  ecx,'4'
   sub     ecx, '0'
        
   mov  edx, '5'
   sub     edx, '0'    ;字符转数字
        
   call    sum          ;调求和函数
   mov  [res], eax      ;结果写入内存
   
   mov  ecx, msg        ;打印消息        
   mov  edx, len
   mov  ebx,1           ;file descriptor (stdout)
   mov  eax,4           ;system call number (sys_write)
   int  0x80            ;call kernel
        
   mov  ecx, res        ;打印结果
   mov  edx, 1
   mov  ebx, 1          ;file descriptor (stdout)
   mov  eax, 4          ;system call number (sys_write)
   int  0x80            ;call kernel
        
   mov  eax,1           ;system call number (sys_exit)
   int  0x80            ;call kernel
sum:                    ;数字相加后转字符
   mov     eax, ecx
   add     eax, edx
   add     eax, '0'
   ret                  ;返回callee继续执行
        
section .data
msg db "The sum is:", 0xA,0xD 
len equ $- msg   

segment .bss
res resb 1

汇编的宏等价于复制粘贴代码块,区别于函数,宏没有call/ret过程,只在编译阶段展开。

语法为

复制代码
%macro macro_name  number_of_params    ;关键字 宏名 参数数量
<macro body>
%endmacro

示例

复制代码
; A macro with two parameters
; Implements the write system call
   %macro write_string 2    ;包装打印字符串的宏
      mov   eax, 4
      mov   ebx, 1
      mov   ecx, %1    ;第一个参数
      mov   edx, %2    ;第二个参数
      int   80h
   %endmacro
 
section .text
   global _start            ;must be declared for using gcc
        
_start:                     ;tell linker entry point
   write_string msg1, len1    ;宏名 第一个参数 第二个参数              
   write_string msg2, len2    
   write_string msg3, len3  
        
   mov eax,1                ;system call number (sys_exit)
   int 0x80                 ;call kernel

section .data
msg1 db 'Hello, programmers!',0xA,0xD   
len1 equ $ - msg1                       

msg2 db 'Welcome to the world of,', 0xA,0xD 
len2 equ $- msg2 

msg3 db 'Linux assembly programming! '
len3 equ $- msg3
相关推荐
我在人间贩卖青春4 天前
汇编之伪指令
汇编·伪指令
我在人间贩卖青春5 天前
汇编之伪操作
汇编·伪操作
济6175 天前
FreeRTOS基础--堆栈概念与汇编指令实战解析
汇编·嵌入式·freertos
myloveasuka5 天前
汇编TEST指令
汇编
我在人间贩卖青春5 天前
汇编编程驱动LED
汇编·点亮led
我在人间贩卖青春5 天前
汇编和C编程相互调用
汇编·混合编程
myloveasuka5 天前
寻址方式笔记
汇编·笔记·计算机组成原理
请输入蚊子6 天前
《操作系统真象还原》 第六章 完善内核
linux·汇编·操作系统·bochs·操作系统真像还原
myloveasuka6 天前
指令格式举例
汇编·笔记·计算机组成原理
我在人间贩卖青春6 天前
汇编之分支跳转指令
汇编·arm·分支跳转