[0x08] nasm汇编 [运算:加减乘除]

本文详细介绍了Nasm汇编语言中的基本运算指令,包括加(add)、减(sub)、乘(mul)和除(div),并通过示例代码解释了如何在汇编语言中进行这些运算。特别强调了mul和div指令的使用方法,以及运算结果的存储位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上节介绍了使用栈调用函数,call指令调用的时候,将当前的IP值压入栈。函数返回的时候,将栈顶的元素pop到IP中,由于默认使用_cdecl调用,因此需要调用者平衡栈。

这节介绍基本的运算:加减乘除。nasm使用Intel汇编指令,可以通过查阅Intel官方文档,这里是Intel指令官方文档:

https://www.intel.cn/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-manual-325462.pdf

代码test8.asm如下:

; test8.asm
; nasm -f elf64 -o test8.o test8.asm
; gcc -o test8 test8.o
; ./test8
extern printf

section .data
	fmt: db '%ld',0xa,0

section .text
global main
main:
	push rbp
	; add
	mov rax, 8
	mov rbx, 123
	add rax, rbx
	; print result	
	mov rdi, fmt
	mov rsi, rax
	mov rax, 0
	call printf
	; sub
	mov rax, 12
	sub rax, 3
	; print result
	mov rdi, fmt
	mov rsi, rax
	mov rax, 0
	call printf
	; mul
	mov rax, 3
	mov rbx, 10
	mul rbx
	; print result	
	mov rdi, fmt
	mov rsi, rax
	mov rax, 0
	call printf
	; div
	mov rdx, 0
	mov rax, 10
	mov rbx, 3
	div rbx 
	mov rdx, rcx
	; print rax
	mov rdi, fmt
	mov rsi, rax
	mov rax, 0
	call printf
	; print rdx
	mov rdi, fmt
	mov rsi, rcx
	mov rax, 0
	call printf

	pop rbp
	; exit
	mov rax, 60
	syscall
	ret	

这段代码虽然比较长,但还算比较简单。add,sub,mul,div都是无符号运算。

add和sub比较好理解,主要介绍mul和div指令。

mov rax, 3
mov rbx, 10
mul rbx

rax存放一个乘数,mul 后面跟一个乘数,结果存放到rdx:rax中。这样的规则可以应用到32位乘法,16位乘法,以及8位的乘法,除法运算也如此。

mov rdx, 0
mov rax, 10
mov rbx, 3
div rbx 

在div指令中,被除数存放到rdx:rax中,除数跟在div指令后面,除法的结果是,rax存放商,rdx存放余数。

 

乘法指令mul占用的CPU周期较多,编译器在优化代码时,会使用左移和加法来执行乘法操作,使用右移和减法来执行除法运算。

执行div和mul后,需要及时处理结果,把结果存放到内存中,否则这些寄存器中的值可能会随着其他代码或函数的执行被修改,而丢失运算结果。

<think>好的,我现在需要帮用户解答如何系统学习汇编语言的问题。首先,回顾用户之前的提问记录,他们之前问了关于__attribute__((unused))的问题,这可能显示他们对底层编程或编译器相关的内容感兴趣。现在转向汇编语言,可能他们希望更深入了解计算机底层工作原理,或者需要优化代码、进行逆向工程等。 用户的问题比较广泛,需要给出一个系统的学习路径。我得考虑不同用户的基础,可能有些是刚入门的,有些可能已有编程经验。但用户之前的问题涉及GCC属性,可能有一定的C语言基础,所以可以假设他们有一定的编程经验,但可能对汇编还不太熟悉。 接下来,我需要整理汇编学习的步骤。通常学习汇编需要从基础开始,比如计算机组成原理、寄存器、内存结构等。然后选择适合的汇编语言,比如x86、ARM,根据用户的需求,可能需要推荐常见的x86架构开始,但也要提到不同架构的选择依据。 然后是工具链的介绍,汇编器、调试器这些工具的使用方法,比如NASM、GDB等。用户可能需要具体的工具使用示例,所以举一些简单的例子会有帮助,比如Hello World程序,这样他们可以快速上手。 之后是指令集的学习,数据传送、算术运算、控制流等,这部分需要循序渐进,强调理解指令的作用和底层操作。同时,内存寻址方式也是重点,需要详细说明不同的寻址模式,并举例说明。 调试和反汇编部分也很重要,学习汇编时调试是必不可少的,可以教用户如何使用GDB查看寄存器和内存状态。反汇编则帮助他们将高级语言代码与汇编对应起来,加深理解。 高级内容如系统调用、优化和混合编程可能适合有一定基础的用户,但需要提到这些方向,让用户知道后续的学习路径。另外,应用领域如逆向工程或嵌入式开发,可以根据用户的兴趣推荐相关资料。 资源推荐方面,书籍和在线资源要兼顾经典和实用。《汇编语言》王爽的书比较适合入门,而《x86汇编语言:从实模式到保护模式》则适合深入。在线教程和实验平台如Godbolt编译器资源管理器能让用户直观看到代码生成的汇编,这对理解编译器行为很有帮助。 最后,学习建议部分要强调实践的重要性,建议用户多写代码、参与项目,同时结合理论知识。保持耐心,因为汇编学习曲线陡峭,但掌握后对理解计算机体系结构帮助很大。 需要避免使用过于专业的术语,保持解释的易懂性,同时结构清晰,分点列出,方便用户逐步学习。检查是否有遗漏的部分,比如是否提到了不同平台(Windows/Linux)的工具差异,或者是否需要强调练习的重要性。可能用户的实际需求是进行底层开发或安全研究,所以应用领域的例子需要覆盖这些方面。 总结来说,回答需要结构清晰,步骤明确,涵盖从基础到进阶的内容,推荐资源,并给出学习建议,鼓励实践和持续学习。</think>学习汇编语言需要从底层理解计算机工作原理,结合实践逐步深入。以下是系统学习的路径和建议: --- ### **一、基础准备** 1. **计算机体系结构基础** - **CPU工作原理**:了解寄存器、ALU、指令周期、内存访问机制。 - **内存模型**:地址空间、堆栈(Stack)与堆(Heap)的区别。 - **二进制与十六进制**:熟练转换二进制/十六进制,理解补码、移位运算。 2. **选择目标架构** - **x86/x86-64**:主流PC架构,适合学习通用编程和逆向分析(推荐初学者)。 - **ARM**:移动设备/嵌入式主流架构,适合物联网开发。 - **RISC-V**:开源指令集,新兴领域(学术/科研常用)。 --- ### **二、学习步骤** #### **1. 工具链掌握** - **汇编器(Assembler)**: - NASM(x86常用)、GAS(GCC默认)、MASM(Windows)。 - **调试器(Debugger)**: - GDB(Linux)、WinDbg/OllyDbg(Windows)、LLDB(macOS)。 - **模拟器**:QEMU(运行汇编代码的环境)。 **示例(x86 Linux环境)**: ```asm ; hello.asm(NASM语法) section .data msg db 'Hello, World!', 0xA len equ $ - msg section .text global _start _start: mov eax, 4 ; sys_write 系统调用号 mov ebx, 1 ; 文件描述符 stdout mov ecx, msg ; 字符串地址 mov edx, len ; 字符串长度 int 0x80 ; 触发系统调用 mov eax, 1 ; sys_exit 系统调用号 xor ebx, ebx ; 返回值 0 int 0x80 ``` 编译与运行: ```bash nasm -f elf32 hello.asm -o hello.o ld -m elf_i386 hello.o -o hello ./hello ``` #### **2. 指令集学习** - **核心指令分类**: | 类型 | 示例指令 | 作用 | |------------|---------------------|---------------------------| | 数据传送 | `mov`, `push`, `pop` | 寄存器/内存间数据传输 | | 算术运算 | `add`, `sub`, `mul` | 加减乘除 | | 位操作 | `and`, `or`, `shl` | 按位运算与移位 | | 控制流 | `jmp`, `call`, `ret`| 跳转与函数调用 | | 条件判断 | `cmp`, `test`, `je` | 比较与条件跳转 | - **内存寻址模式**: - 立即寻址:`mov eax, 42` - 寄存器寻址:`mov ebx, eax` - 直接寻址:`mov ecx, [0x1000]` - 寄存器间接寻址:`mov edx, [esi]` - 基址变址寻址:`mov eax, [ebx + esi*4 + 8]`(x86) #### **3. 调试与反汇编** - **使用GDB调试汇编程序**: ```bash gdb -q ./hello (gdb) break _start # 设置断点 (gdb) run # 运行程序 (gdb) info registers # 查看寄存器 (gdb) x/10i $pc # 反汇编当前指令 ``` - **反汇编高级语言代码**: 通过 `objdump` 或编译器输出观察C代码对应的汇编: ```bash gcc -S -O0 test.c # 生成 test.s 汇编文件 ``` #### **4. 进阶内容** - **系统调用与中断**: - Linux:通过 `int 0x80` 或 `syscall` 调用内核功能(需熟悉系统调用表)。 - Windows:通过API或 `syscall` 直接调用(需了解PE结构)。 - **优化技巧**: - 减少内存访问(多用寄存器)。 - 指令流水线优化(避免数据依赖)。 - **混合编程**: 在C语言中内嵌汇编(GCC扩展语法): ```c int add(int a, int b) { int result; __asm__("addl %%ebx, %%eax;" : "=a"(result) : "a"(a), "b"(b)); return result; } ``` --- ### **三、学习资源** 1. **书籍推荐** - 《汇编语言》(王爽):中文经典,侧重x86实模式。 - 《x86汇编语言:从实模式到保护模式》:深入理解CPU模式切换。 - 《Computer Systems: A Programmer's Perspective》(CS:APP):第3章讲解汇编与系统。 2. **在线教程与工具** - **互动学习**: - [Godbolt编译器资源管理器](https://godbolt.org/):实时查看C代码生成的汇编。 - [ASM Primer](https://asm.pages.dev/):交互式汇编教程。 - **逆向练习**: - CrackMe挑战([例题](https://crackmes.one/))通过逆向学习汇编。 3. **实践项目** - 实现基础算法(排序、字符串操作)。 - 编写Bootloader(需QEMU模拟器)。 - 修改程序行为(如游戏外挂或补丁)。 --- ### **四、应用领域** - **逆向工程**:分析恶意软件或闭源程序。 - **性能优化**:优化关键代码(如游戏引擎、高频交易)。 - **嵌入式开发**:直接操作硬件(如Arduino汇编编程)。 - **操作系统开发**:编写内核或驱动。 --- ### **五、学习建议** 1. **从简单架构入手**:建议先学x86-32位(实模式),再扩展到64位或ARM。 2. **动手实践**:每学一条指令,立刻写代码验证。 3. **结合高级语言**:通过C/C++内嵌汇编,理解编译器行为。 4. **参与社区**:如Stack Overflow、OSDev论坛提问交流。 掌握汇编后,你会对计算机底层有更深刻的理解,无论是开发、安全还是系统优化,都能游刃有余。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值