欢迎访问察北家纺网

伪代码怎么写(中文论文中伪代码怎么写)

频道:家有妙招 日期: 浏览:1225

       伪代码是给处理器的指令,它实际上是原始十六进制代码的可读版。因此,汇编是最低级的编程语言。汇编中的所有东西被直接翻译为十六进制码。换句话说,你没有把高级语言翻译为低级语言的编译器上的烦恼,汇编器仅仅把汇编代码转化为原始数据。

       下面将讨论一些用来运算,位操作等的伪代码。还有跳转指令,比较等伪代码。

       1.一些基本的计算伪代码(又称指令)

       (1)MOV

       这条指令用来把一个地方移往(事实上是复制到)另一个地方。这个地方可以是寄存器,内存地址或是直接数值(当然只能作为源值)。Mov指令的语法是:

       mov 目标,源

       你可把一个寄存器移往另一个(注意指令是在复制那个值到目标中,尽管"mov"这个名字是移的意思)

       mov edx, ecx

       上面的这条指令把ecx的内容复制到了ecx中,源和目标的大小应该一致。例如这个指令是非法的:

       mov al, ecx;非法

       这条伪代码试图把一个DWORD(32位)值装入一个字节(8位)的寄存器中。这不能个由mov指令来完成(有其他的指令干这事)。但这些指令是允许的因为源和目标在大小上并没有什么不同:

       mov al, blmov cl, dlmov cx, dxmov ecx, ebx

       内存地址由offset指示(在win32中,前一章中有更多信息)你也能从地址的某一个地方获得一个值并把它放入一个寄存器中。下面有一个例子:

       每一个块代表一个字节

       offset的值这里是用字节的形式表示的,但它事实上是32位的值,比如3A(这不是一个常见的offset的值,但如果不这样简写表格装不下),这也是一个32位的值:0000003Ah。只是为了节省空间,使用了一些不常见的低位offset。所有的值均为16进制。

       看上表的offset 3A。那个offset的数据是25, 7A, 5E, 72, EF等。例如,要把这个位于3A的值用mov放入寄存器中:

       mov eax, dword ptr[0000003Ah]

       (h后缀表明这是一个十六进制值)

       mov eax, dword ptr[0000003Ah]这条指令的意思是:把位于内存地址3A的DWORD大小的值放入eax寄存器。执行了这条指令后,eax包含了值725E7A25h。可能你注意到了这是在内存中时的反转结果:25 7A 5E 72。这是因为存储在内存中的值使用了little endian格式。这意味着越靠右的字节位数越高:字节顺序被反转了。我想一些例子可以使你把这个搞清楚。

       十六进制dword(32位)值放在内存中时是这样:40, 30, 20, 10(每个值占一个字节(8位))

       十六进制word(16位)值放在内存中时是这样:50, 40

       回到前面的例子。你也可以对其他大小的值这么做:

       mov cl, byte ptr [34h] ; cl得到值0Dh(参考上表)

       mov dx, word ptr [3Eh] ; dx将得到值 7DEFh (看上表,记住反序)

       大小有时不是必须的。

       Mov eax,[00403045h]

       因为eax是32位寄存器,编译器假定(也只能这么做)它应该从地址403045(十六进制)取个32位的值。

       可以直接使用数值:

       mov edx, 5006

       这只是使得edx寄存器装有值5006,综括号[和]用来从括号间的内存地址处取值,没有括号就只是这个值。寄存器和内存地址也可以(他应该是32位程序中的32位寄存器):

       mov eax,403045h;使eax装有值403045h(十六进制)

       mov cx,[eax];把位于内存地址eax的word大小的值(403045)移入cx寄存器。

       在mov cx, [eax]中,处理器会先查看eax装有什么值(=内存地址),然后在那个内存地址中有什么值,并把这个word(16位,因为目标-cx-是个16位寄存器)移入cx。

       (2)ADD, SUB, MUL, DIV

       许多伪代码做计算工作。你可以猜出它们中的大多数的名字:add(加),sub(减),mul(乘),div(除)等。

       Add伪代码有如下语法:

       Add 目标,源

       执行的运算是 目标=目标+源。下面的格式是允许的。

       这条指令非常简单。它只是把源值加到目标值中并把结果保存在目标中。其他的数学指令有:

       sub 目标,源(目标=目标-源)mul 目标,源(目标=目标×源)div 源(eax=eax/源,edx=余数)

       减法和加法一样做,乘法是目标=目标×源。除法有一点不同,因为寄存器是整数值(注意,绕回数不是浮点数)除法的结果被分为商和余数。例如:

       28/6->商=4,余数=430/9->商=3,余数=397/10->商=9,余数=718/6->商=3,余数=0

       现在,取决于源的大小,商(一部分)被存在eax中,余数(一部分)在edx:

       *:例如,如果dx=2030h,而ax=0040h,dx:ax=20300040h。dx:ax是一个双字值。其中高字代表dx,低字代表ax,Edx:eax是个四字值(64位)其高字是edx低字是eax。

       Div伪代码的源可以是

       · 8位寄存器 (al, ah, cl,...)

       · 16位寄存器 (ax, dx, ...)

       · 32位寄存器 (eax, edx, ecx...)

       · 8位内存数 (byte ptr [xxxx])

       · 16位内存数(word ptr [xxxx])

       · 32位内存数(dword ptr [xxxx])

       源不可以是直接数值,因为处理器不能决定源参数的大小。

       (3)位操作

       这些指令都由源和目标,除了"NOT"指令。目标中的每位与源中的每位作比较,并看是那个指令,决定是0还是1放入目标位中。

       如果源和目标均为1,AND把输出位设为1。

       如果源和目标中有一个为1,OR把输出位设为1。

       如果源和目标位不一样,XOR把输出位设为1。

       NOT反转源位

       一个例子:

       mov ax, 3406mov dx, 13EAhxor ax,dx

       ax=3406(十六进制)是二进制的0000110101001110

       dx=13EA(十六进制)是二进制的0001001111101010

       对这些位进行xor操作:

       新dx是0001111010100100 (十进制的7845, 十六进制的1EA4)

       另一个例子:

       mov ecx, FFFF0000hnot ecx

       FFFF0000在二进制中是11111111111111110000000000000000(16个1,16个0)如果反转每位会得到

       00000000000000001111111111111111(16个0,16个1)在十六进制中是0000FFFF。因而执行NOT操作后,ecx是0000FFFFh。

       (4)步增INC/步减DEC

       有两个很简单的指令,DEC和INC。这些指令使内存地址和寄存器步增或步减,就是这样:

       inc reg -> reg = reg + 1

       dec reg -> reg = reg – 1

       inc dword ptr [103405] -> 位于103405的值步增

       dec dword ptr [103405] -> 位于103405的值步减

       (5)NOP

       这条指令什么都不干。它仅仅占用空间和时间。它用作填充或给代码打补丁的目的。

       (6)移位(Bit Rotation 和 shifiting)

       注意:下面的大部分例子使用8位数,但这只是为了使目的清楚。

       (7)Shifting函数

       SHL 目标,计数(count)

       SHR 目标,计数(count)

       SHL和SHR在寄存器,内存地址中像左或向右移动一定数目(count)的位。

       例如:

       ;这儿al=01011011(二进制)

       shr al, 3

       它的意思是:把al寄存器中的所有位向右移三个位置。因而al会变成为00001011。左边的字节用0填充,而右边的字节被移出。最后一个被移出的位保存在carry-flag中。Carry-flag是处理器标志寄存器的一位,它不是像eax或ecx一样的,你可以访问的寄存器(虽然有伪代码干这活),但它的值决定于该指令的结构。它(carry-flag)会在后面解释,你要记住的唯一一件事是carry是标志寄存器的一位且它可以被打开或者关闭。这个位等于最后一个移出的位。

       shl和shr一样,只不过是向左移。

       ;这儿bl=11100101(二进制)

       shl bl, 2

       执行了指令后bl是10010100(二进制)。最后的两个位是由0填充的,carry-flag是1,因为最后移出的位是1。

       还有两个伪代码:

       SAL 目标, 计数(算术左移)

       SAR 目标, 计数(算术右移)

       SAL和SHL一样,但SAR不完全和SHR一样。SAR不是用0来填充移出的位而是复制MSB(最高位)例如:

       al = 10100110

       sar al, 3

       al = 11110100

       sar al, 2

       al = 11101001

       bl = 00100110

       sar bl, 3

       bl = 00000100

       (8)Rotation(循环移动) 函数

       Rol 目标,计数;循环左移

       Ror 目标,计数;循环右移

       Rcl 目标,计数;通过carry循环左移

       Rcr 目标,计数;通过carry循环右移

       循环移动(Rotation)看上去就像移(Shifting),只是移出的位又到了另一边。

       例如:ror(循环右移)

       如你在上图所见,位循环了。注意,每个被推出的位又移到了另一边。和Shifting一样,carry位装有最后被移出的位。Rcl和Rcr实际上和Rol,Rcr一样。它们的名字暗示了它们用carry位来表明最后移出的位,但和Rol和Ror干同样的事情。它们没有什么不同。

       (9)交换

       XCHG指令也非常简单。它同在两个寄存器和内存地址之间交换:

       eax = 237h

       ecx = 978h

       xchg eax, ecx

       eax = 978h

       ecx = 237h

技术和通信的概念

       2.条件跳转

       例如下面这段代码:

       mov eax, edx

       sub eax, ecx

       cmp eax, 2

       jz loc1

       xor eax, eax

       jmp loc2

       loc1:

       xor eax, eax

       inc eax

       loc2:

       (xor eax, eax意为:eax=0,eax清零)

       让我们来看看这些代码:

       mov eax, edx ;把edx放入eax中

       sub eax, ecx ;eax-ecx

       cmp eax, 2

       这有一条新指令:cmp。Cmp意为compare(比较)。它能比较两个值(或寄存器、或内存、或直接数值)并设置Z-flag(零标志)。零标志很像carry,也是内部标志寄存器的一位。

       Jz loc1

       这也是条新的。它是条件跳转指令。Jz=jump if zero(如果设置了零标志就跳转)。Loc1是一个标记指令"xor eax,eax|inc eax"内存开始处offset的标签。因而jz loc1=如果设置了零标志,跳往位于loc1的指令。

       Cmp eax, 2;如果eax=2设置零标志

       Jz loc1;如果设置了零标志就跳转

       = 如果eax等于2,跳往位于loc1的指令

       然后有jmp loc2.这也好似一个跳转,但是是一个无条件跳转:它总是执行。上面的代码,用c语言描述就是:

       if ((edx-ecx)==2)

       {

       eax = 1;

       }

       Else

       {

       eax = 0;

       }

       或者,用Basic语言描述:

       IF (edx-ecx)=2 THEN

       EAX = 1

       ELSE

       EAX = 0

       END IF

程序员职业-编写程序代码在笔记本电脑上

       3.标志寄存器

       标志寄存器有一套标志。它们设不设置取决于计算或其他时间。我不会讨论它们的全部。只拣几个重要的说:

       还有更多的标志(Parity, Auxiliary, Trap, Interrupt, Direction, IOPL, Nested Task, Resume, & Virtual Mode)但因为我们不用它们,所以我不解释。

Unix 词云

       4.跳转系列

       有一整套的条件跳转,而且它们跳转与否均取决于标志的状态。但由于大部分跳转指令有明白的名字,你甚至无需知道哪个标志要设置,例如:"如果大于等于就跳转"(jge)和"符号标志=溢出标志"一样,而"如果零就跳转"和"如果零标志=1就跳转"一样。死背住下面的表即可

       在下表中,"意思"指的是什么样的计算结果该跳转。"如果大于就跳转"意为:

       cmp x, y

       jump 如果 x 比 y大 就跳

       所有的跳转指令后面要跟一个参数:要跳往的偏移地址(距离)offset。