全部学习汇总: GreyZhang/g_unix: some basic learning about unix operating system. (github.com)
这一次简单看看条件分支以及控制结构,感觉看完这部分之后,汇编的大部分框架已经有个差不多了。我的目的并不是成为汇编高手,因此剩下的部分直接快进即可了。
这是提供的几种跳转分支,类似GOTO,只是这个GOTO是带条件的。其实这些我并不陌生,大学时候的记忆还在。
上面的例子展示了一个比较简单的例子,条件赋值。其实,跟着指令走还是很容易理解机器的行为意图的。但是如果看完之后,想要翻译成一个高级语言可能并不是那么容易。第二个例子,其实是展示了一点“图灵完备”的意思了,纵然不好用但是也可以解决问题。然而,CPU其实有更好的设计。
这就是前面所谓的更好的设计了,算是进行了很多情况的复杂细分应对。而下面的这个例程实现则是简单的多了。
这里给出来了一个循环的例子,只是这个循环让人有点觉得不舒服。因为需要转换一下表达的思路,才能够把加法处理改成减法处理。接下来,给了一个实现条件分支的汇编模板。
这里的两种循环结构,理解也是很容易的。其实,只需要结合C语言加入一个语素就能够理解,那就是把跳转转换成break或者continue。
这一段代码在开始附加了一段C语言实现,由此再进行相关的汇编实现只是一个翻译工作了。从这种思考角度来进行软件设计也是一个思考的方式。
我最初做这个代码分析的时候并没有看原始的C代码,也没有注意到里面写了前两个作为特殊的对象处理。当时看到这里觉得这个程序有问题,因为无论截止数值是多少前两个数都会输出。测试结果自然也是如此,但是这个是这个程序本身想处理的。
剩余的部分解析也很容易。不过,这种设计也不过是拿来辅助一下对于汇编这个工具的使用。类似这样的软件设计自然还是直接高级语言处理来的更加现实一些。
顺利编译,makefile还是需要修改的。以下是运行的结果:
最后,附加增补了注释的源代码如下:
;
; file: prime.asm
; This program calculates prime numbers
;
; To create executable:
; nasm -f coff prime.asm
; gcc -o prime prime.o driver.c asm_io.o
;
; Works like the following C program:
; #include <stdio.h>
;
;int main()
;{
; unsigned guess; /* current guess for prime */
; unsigned factor; /* possible factor of guess */
; unsigned limit; /* find primes up to this value */
;
; printf("Find primes up to: ");
; scanf("%u", &limit);
;
; printf("2\n"); /* treat first two primes as special case */
; printf("3\n");
;
; guess = 5; /* initial guess */
; while ( guess <= limit ) {
; /* look for a factor of guess */
; factor = 3;
; while ( factor*factor < guess && guess % factor != 0 )
; factor += 2;
; if ( guess % factor != 0 )
; printf("%d\n", guess);
; guess += 2; /* only look at odd numbers */
; }
; return 0;
;}
;
%include "asm_io.inc"
segment .data
Message db "Find primes up to: ", 0
segment .bss
Limit resd 1 ; find primes up to this limit
Guess resd 1 ; the current guess for prime
segment .text
global asm_main
asm_main:
enter 0,0 ; setup routine
pusha
mov eax, Message
call print_string
call read_int ; scanf("%u", & limit );
mov [Limit], eax
; 从这里看,其实2和3是一直会输出的,因此这个程序应该会有bug
mov eax, 2 ; printf("2\n");
call print_int
call print_nl
mov eax, 3 ; printf("3\n");
call print_int
call print_nl
mov dword [Guess], 5 ; Guess = 5;
;; 从第三个质数开始猜测,如果这个就已经大于了限制数值那么直接结束即可
while_limit: ; while ( Guess <= Limit )
mov eax,[Guess]
cmp eax, [Limit]
jnbe end_while_limit ; use jnbe since numbers are unsigned
mov ebx, 3 ; ebx is factor = 3;
;; 查看是否还有其他的因子
while_factor:
mov eax,ebx
mul eax ; edx:eax = eax*eax
;; 这个应该是已经超出了处理极限了,因此直接结束
jo end_while_factor ; if answer won't fit in eax alone
;; 如果还在处理的范围内,看看猜测的因子乘积是否大于猜测值
cmp eax, [Guess]
;; 如果因子的平方大于等于猜测值,直接结束因子测试
;; 否则看看是否整除,如果整除结束
jnb end_while_factor ; if !(factor*factor < guess)
mov eax,[Guess]
mov edx,0
div ebx ; edx = edx:eax % ebx
cmp edx, 0
je end_while_factor ; if !(guess % factor != 0)
add ebx,2 ; factor += 2;
jmp while_factor
end_while_factor:
;; 如果测试完了所有的因子不整除,那么是质数
je end_if ; if !(guess % factor != 0)
mov eax,[Guess] ; printf("%u\n")
call print_int
call print_nl
end_if:
mov eax,[Guess]
add eax, 2
mov [Guess], eax ; guess += 2
jmp while_limit
end_while_limit:
popa
mov eax, 0 ; return back to C
leave
ret