更新时间 2021-07-16

hello world 相信大多数人的第一个程序,都是下面的这段代码。或者差不多是这样。不过编译器最终生成的汇编代码是怎样的,是一个比较有趣的事情,那么这里我们分析一下。 #include <stdio.h> int main() { printf("hello world!!!\n"); return 0; } 我们可以用下面的命令生成汇编代码: gcc -S hello.c .file "hello.c" .text .section .rodat

下面是一个 hello world!!! 程序使用 nasm 汇编,调用 32位系统调用,然后退出的程序。过程简单,但是存在一个问题 …… [bits 32] section .text global main main: mov eax, 4; write mov ebx, 1; stdout mov ecx, message; buffer mov edx, message_end - message int 0x80 mov eax, 1; exi

更新时间 2021-05-12

结构体和 C++ 结构体是 C 语言将相互有关联的数据组合到一个变量中的一种方式。这个技术有几个优势: 相关数据定义更加紧密使得代码更加清晰 简化参数传递,将多个参数合在一起 增强了代码的内聚 站在汇编的角度,结构可以看成是数组,其中的元素大小不一。 例如: typedef struct S { short x; int y; double z; } S; int test() { S s; s.x = 1; s.y = 2; s.z = 4.0

更新时间 2021-05-12

什么是汇编语言 处理器指令 IA-32 指令码格式由四部分组成: 可选指令前缀 指令码 可选指令修改器 可选数据元素 指令码 指令码是指令格式中必须提供的,指示处理器应该执行什么功能或者任务。 指令码的长度为 1 ~ 3 字节不等,例如 OF A2 表示了 cupid 指令,执行该指令时,处理器会把当前微处理器的信息存储到不同的寄存器。 指令前缀 指令前缀可以包含 1 ~ 4 个字节的信息,来修改指令码的行为。指令前缀可分为四类: 锁前缀和重复前缀 段重写前缀和分支提示前缀 操作数大小前缀 地址大小

更新时间 2021-05-04

前面介绍了计算机从加电一直到主引导扇区加载到 0x7c00 的位置,然后继续执行。 那么这里介绍一下 8086 CPU 的寄存器,8086 有 14 个寄存器。 如果看过之前《CPU设计和实现》的同学呢,应该能够直到寄存器内部实际上是一堆 D 边沿触发器,这个是很关键的,可以对寄存器有个感性的认识。那么下面来说一下 8086 的寄存器。寄存器可以分为四类。分别对应不同的功能。 通用寄存器 寄存器 描述 AX 累加结果数据 BX 数据段数据指针 CX 字符串和循环计数器 DX I/O

更新时间 2021-05-03

重新编译 bochs 由于 bochs-2.6.11 gtk GUI 的源码有 bug,导致无法查看 堆栈,以及其他的一些调试工具,所以下面重新编译 bochs 有以下两个文件 PKGBUILD # Maintainer: Kyle Keen <keenerd@gmail.com> # Contributor: Tom Newsom <Jeepster@gmx.co.uk> # Contributor: Kevin Piche <kevin@archlinux.org> pkgname=bochs pkg

Bochs X86体系的模拟器,是一个虚拟机,用于调试操作系统,当然也可以用于学习 X86 汇编语言。 安装 Bochs 在 Archlinux 中可以执行以下的命令来安装 Bochs pacman -S bochs 配置 Bochs 直接在命令行输入 bochs 得到如下的结果 You can also start bochs with the -q option to skip these menus. 1. Restore factory default configuration 2. Read