仅用60字节的HelloWorld程序?!使用汇编编写Hello World!

需要注意的是,此版本并不是对视频的完全文字化,而是对视频的一个扩充,两者也各有不同。其中有比Hello World更高级的递归程序,也会提供工具。

导入

递归递归,只递不归。装13起劲,内存炮灰

哈哈,刚刚的那首诗是不是很有意思,今天的主题就是汇编。

汇编汇编,你很有可能在各种网站上见到有人说汇编如何如何。不过现在汇编就跟以前的大小端模式一样,已经不是普通程序员所需要的了。

汇编是一种很低级的语言,直接操控计算机内存和CPU还有操作系统。

所以编写起来会相当麻烦,你知道进入DOS后主板的蜂鸣器响是由什么程序完成的吗?

这个响声是由debug.exe完成的,debug.exe是一个基于命令行的调试工具,出现在MS-DOS和Microsoft Windows的早期版本中。

它允许用户以汇编语言的形式直接与计算机的硬件交互,进行内存读写、执行机器指令等操作。

debug.exe提供了一些操作指令用于操控计算机硬件,常用命令如下。

  • d - 显示内存区域的内容。
  • e - 修改内存区域的内容。
  • r - 显示寄存器的内容。
  • w - 写入数据到指定的内存位置。
  • u - 将十六进制数据转换成可执行的机器码并写入内存。
  • g - 执行从指定地址开始的代码。
  • q - 退出 debug 程序。
  • a - 将 ASCII 字符串转换成机器码并写入内存。

在其中最重要的就是a指令了,这个命令特别有用,当你想要将一段汇编语言指令作为文本字符串输入,然后将其转换成二进制形式存储在内存中。

程序

代码

代码只有6行,非常的简单

mov dx,010b
mov ah,09
int 21
mov ah,4c
int 21
db "Hello World$"
  • mov dx, 010b:
    • 这一行将二进制值010b(在二进制中010b等于十进制的2)赋给寄存器DX。是一个指向字符串的偏移地址。
  • mov ah, 09:
    • 这一行将数值09移动到寄存器AH中。设置AH寄存器为09h,准备调用中断int 21h中的功能号09h,即打印带有换行的字符串。
  • int 21:
    • 这一行调用中断21h
  • mov ah, 4c:
    • 这一行设置了AH寄存器的值为4Ch,这是退出程序的功能号。
  • int 21:
    • 这一行再次调用中断21h,这次是使用之前设置的AH值来执行退出程序的操作。
  • db "Hello World$":
    • 这一行定义了一个数据区(data byte),其中包含了字符串"Hello World"

 输入

使用a命令进入内存,然后将所有的汇编代码输入进去

输入完成后程序需要存盘

使用R命令修改寄存器cx的值为3c

rcx 3c

n命令指定存盘后的程序名称

w存盘

q命令退出

好了,你现在已经有了一个汇编的Hello world程序了,快去试试吧!

更高级的汇编

你还记得我们在开头的有趣的诗的吗,这个程序将会做一个实现。

警告!此程序会让计算机异常运行,此程序仅用作教学目的。

section .data
section .bss
section .text
global _start

_start:
    ; 开始无限递归
    call recursive_call

recursive_call:
    ; 保存寄存器状态
    push rbp
    mov rbp, rsp

    ; 打印一些信息,当前递归深度
    ; 这里我们简单地输出一条消息
    mov rax, 1       ; sys_write (系统调用编号, 在 64 位模式下是 1)
    mov rdi, 1       ; file descriptor (stdout)
    lea rsi, [msg]   ; 消息的地址
    mov rdx, msg_len ; 消息长度
    syscall          ; 调用内核 (64 位模式下的系统调用)

    ; 无限递归调用
    call recursive_call

    ; 恢复寄存器状态
    mov rsp, rbp
    pop rbp
    ret

section .data
msg db 'HAHAHAHAHA: ', 0
msg_len equ $ - msg

此程序只能在x86-64的CPU下运行

编译

nasm -f elf64 infinite_recursion.asm -o infinite_recursion.o

链接

ld -m elf_x86_64 infinite_recursion.o -o infinite_recursion

运行

./infinite_recursion

如果你需要编译好的程序

本内容需要登录后查看

16位DOS版

 

 

.model small
.stack 100h

.data
msg db 'Recursion depth: $'  ; 终止字符 '$' 用于 DOS 中断调用

.code
_start:
    ; 开始无限递归
    recursive_call

recursive_call:
    ; 保存寄存器状态
    push ax
    push bx
    push cx
    push dx

    ; 打印一些信息,当前递归深度
    ; 这里我们简单地输出一条消息
    lea dx, msg           ; 消息的地址
    mov ah, 09h           ; 打印字符串中断调用
    int 21h               ; 调用 DOS

    ; 无限递归调用
    call recursive_call

    ; 恢复寄存器状态
    pop dx
    pop cx
    pop bx
    pop ax
    ret

end _start

使用 TASM (Turbo Assembler) 编译程序:

tasm infinite_recursion.asm -t listing -mlist.asm -alisting.asm -lstlisting.lst -coff infinite_recursion.obj

使用 TLINK 链接程序:

tlink infinite_recursion.obj

运行程序:

infinite_recursion

如果你没有条件使用TASM,你也可以使用FASM作为替代在Windows下编译好再送到DOS中运行

可以从官方网站 http://flatassembler.net 下载 FASM

使用FASM编译程序

fasm -f obj -g coff infinite_recursion.asm infinite_recursion.obj

你还需要使用Microsoft的Link工具

link infinite_recursion.obj /subsystem:DOS /machine:i386 /out:infinite_recursion.exe

Link工具包含在Visual Studio 和 Windows SDK中,如果你有WinDBG也会有Link工具

这样你就可以搞破坏学习递归了

阅读剩余
THE END