汇编:语法速通

文章目录

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 天前
学习嵌入式的第三十九天——ARM——汇编
汇编·arm开发·学习
7hhhhhhh5 天前
自学嵌入式第四十四天:汇编
汇编
出门吃三碗饭5 天前
编译器构造:从零手写汇编与反汇编程序(二)
汇编·人工智能·机器学习
JCBP_13 天前
QT(4)
开发语言·汇编·c++·qt·算法
sheepwjl14 天前
《嵌入式硬件(十二):基于IMX6ULL的时钟操作》
汇编·arm开发·单片机·嵌入式硬件·时钟·.s编译
DebugKitty15 天前
硬件开发2-ARM裸机开发1-I.MX6ULL - 汇编点灯
汇编·makefile·imax6ull·gpio·电路复用
我菜就多练15 天前
ARM-汇编的基础知识
汇编·arm开发
(Charon)15 天前
函数之间跳转的实现方式详解:setjmp/longjmp、ucontext 与汇编
汇编
起个昵称吧16 天前
立即数、栈、汇编与C函数的调用
c语言·开发语言·汇编