NASM汇编发起系统调用输出Hello World

NASM汇编发起系统调用输出Hello World

1. 汇编程序输出Hello World的4种方式

  1. 向显存中直接写入数据
  2. 调用DOS中断
  3. 调用BIOS中断
  4. 发起系统调用(System Call)

对于第一种方式,直接操作显存,进程应该是不允许直接操作显存的。我有使用代码尝试,如下代码:

SECTION .data
msg db 'Hello, World!', 0xa
len equ $ - msg

SECTION .text
    global _start
_start:

	mov ax, 0xb800
	mov gs, ax

    mov byte [gs:0x00],'h'
    mov byte [gs:0x02],'e'
    mov byte [gs:0x04],'l'
    mov byte [gs:0x06],'l'
    mov byte [gs:0x08],'o'
    jmp $

可以编译和链接,但是在执行时,会报错:

Segmentation fault (core dumped)

应该是保护模式下操作系统不会让进程直接操作显存。

对于第二种方式,调用DOS中断,只能在DOS系统下使用,本质上也是向显存写入数据。

对于第三种方式,调用BIOS中断,只能在实模式下使用,本质上也是向显存中写入数据,因此也应该是不行的。

这里主要讲讲第四种方式,用汇编语言发起系统调用,在控制台输出Hello, World。

2. 汇编发起Linux系统调用

2.1 发起系统调用的步骤

汇编发起Linux系统调用,有一下几个步骤:

  1. 给ax(eax)寄存器赋值系统调用号
  2. 把参数赋值到其他寄存器,如bx(ebx),cx(ecx)等。
  3. 使用int 0x80发起中断,0x80该中断号表示系统调用。
  4. 如果有返回值,结果会保存到ax(eax)。
2.2 系统调用号对应表

给ax/eax赋值不同的系统调用号,发起的是不同的系统调用,下面是不同的系统调用号对应的不同的系统调用:

系统调用名称eax应存放的系统调用号ebx寄存器参数ecx寄存器参数edx寄存器参数
sys_exit1
sys_fork2struct pt_regs
sys_read3unsigned intchar *size_t
sys_write4unsigned intconst char *size_t
sys_open5const char *intint
sys_close6unsigned int
2.3 发起系统调用输出Hello, World

例如下面代码Hello.asm,调用sys_write系统调用,输出信息:

; Hello.asm
section .data
    msg db "Hello, world", 10 ; 定义字符串,字符串起始地址用符号msg表示
    len equ $-msg ; 表示字符串的长度

section .text
    global _start ; 声明该程序入口是_start处

_start:
    mov edx, len ; 把要打印的字符串长度保存到edx寄存器
    mov ecx, msg ; 把要输出的字符串地址放入ecx寄存器
    mov ebx, 1 ; 1表示stdout标准输出
    mov eax, 4 ; 发起sys_write系统调用
    int 0x80

    mov ax, 1
    int 0x80 ; 发起系统调用,sys_exit

输入下面命令,将源文件Hello.asm,编译,会生成Hello.o文件:

nasm -f elf Hello.asm

然后输入下面命令,把Hello.o文件进行链接,生成可执行文件Hello

ld -m elf_i386 Hello.o -o  Hello

然后输入下面命令,执行Hello可执行文件,成功输出Hello, World:

./Hello

过程图片如下图:

image-20210317214224425

2.4 更多代码练习

如下面的代码,发起系统调用读取用户输入的数据,并输出到控制台:

; 
section .data                           ;Data segment
   userMsg db 'Please enter a number: ' ;Ask the user to enter a number
   lenUserMsg equ $-userMsg             ;The length of the message
   dispMsg db 'You have entered: '
   lenDispMsg equ $-dispMsg                 

section .bss           ;Uninitialized data
   num resb 5
	
section .text          ;Code Segment
   global _start
	
_start:                ;User prompt
   mov eax, 4
   mov ebx, 1
   mov ecx, userMsg
   mov edx, lenUserMsg
   int 80h

   ;Read and store the user input
   mov eax, 3
   mov ebx, 2
   mov ecx, num  
   mov edx, 5          ;读取5个字符(包括回车)
   int 80h
	
   ;Output the message 'The entered number is: '
   mov eax, 4
   mov ebx, 1
   mov ecx, dispMsg
   mov edx, lenDispMsg
   int 80h  

   ;Output the number entered
   mov eax, 4
   mov ebx, 1
   mov ecx, num
   mov edx, 5
   int 80h  
    
   ; Exit code
   mov eax, 1
   mov ebx, 0
   int 80h

image-20210317220529632

  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值