编辑“︁
Intel 8086
”︁(章节)
跳转到导航
跳转到搜索
Template:Editnotice load/content
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
===实例代码=== 以下8086/8088[[汇编语言|汇编]]源代码是将给定大小的数据块从一个位置拷贝到另一个位置的叫做<code>_memcpy</code>的子程序。每次拷贝一个字节,数据移动和循环逻辑采用16位操作。 <!--NOTE: This is not intended to be optimized code, but to illustrate the variety of instructions available on the CPU--> <!--NOTE: The hex codes were assembled by hand, so there may be errors--> {| | <pre> 0000:1000 0000:1000 0000:1000 55 0000:1001 89 E5 0000:1003 06 0000:1004 8B 4E 06 0000:1007 E3 11 0000:1009 8B 76 04 0000:100C 8B 7E 02 0000:100F 1E 0000:1010 07 0000:1011 8A 04 0000:1013 88 05 0000:1015 46 0000:1016 47 0000:1017 49 0000:1018 75 F7 0000:101A 07 0000:101B 5D 0000:101C 29 C0 0000:101E C3 0000:101F </pre> | <syntaxhighlight lang="nasm"> ; _memcpy(dst, src, len) ; Copy a block of memory from one location to another. ; ; Entry stack parameters ; [BP+6] = len, Number of bytes to copy ; [BP+4] = src, Address of source data block ; [BP+2] = dst, Address of target data block ; ; Return registers ; AX = Zero org 1000h ; Start at 0000:1000h _memcpy proc push bp ; Set up the call frame mov bp,sp push es ; Save ES mov cx,[bp+6] ; Set CX = len jcxz done ; If len=0, return mov si,[bp+4] ; Set SI = src mov di,[bp+2] ; Set DI = dst push ds ; Set ES = DS pop es loop mov al,[si] ; Load AL from [src] mov [di],al ; Store AL to [dst] inc si ; Increment src inc di ; Increment dst dec cx ; Decrement len jnz loop ; Repeat the loop done pop es ; Restore ES pop bp ; Restore previous call frame sub ax,ax ; Set AX = 0 ret ; Return end proc </syntaxhighlight> |} 上面的代码使用BP(基指针)寄存器建立一个[[调用栈|调用帧]](包含子程序执行过程中的所有参数和局部变量的栈的区域)。这种[[调用约定]]支持[[reentrancy (computing)|可重入]]和[[递归 (计算机科学)|递归]]代码,大多数类ALGOL语言上世纪50年代后期就已采用这种约定。ES段寄存器保存在堆栈上,并用DS段寄存器中的值替换,于是指令{{code|MOV}} {{code|AL}}会在相同的源数据段和目的数据段之间操作。在返回前,子程序恢复了ES寄存器以前的值。 上面的子程序是一种比较麻烦的拷贝成块数据的方法。若源数据区域和目的数据区域都是处于单个65,536字节的段中(上述程序的要求),使用8086的块<code>MOV</code>指令更有优势。上面的循环部分可以替换为: {| | <pre> 0000:1011 F2 0000:1012 A5 </pre> | <syntaxhighlight lang=nasm> loop rep ; Repeat until CX=0 movsw ; Move the data block </syntaxhighlight> |} 这种方法每次可以拷贝一个字。<code>REP</code>指令使下面的<code>MOVSW</code>重复直至CX=0,重复之时自动递增SI和DI。另外,<code>MOVSB</code>或<code>MOVSD</code>指令可以用来一次拷贝单个字节或双字。大多数汇编器在<code>REP</code>指令用在<code>MOVSW</code>之前为<code>REP MOVSW</code>的情况下都会正确汇编。 如果被中断,这个程序也能正确运行,因为程序计数器会继续指向<code>REP</code>指令,知道块拷贝已经结束。拷贝会在中断服务程序将控制恢复的时候继续。
摘要:
请注意,所有对Local Chinese Wikipedia的贡献均可能会被其他贡献者编辑、修改或删除。如果您不希望您的文字作品被随意编辑,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源(详情请见
Project:著作权
)。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)
导航菜单
个人工具
未登录
讨论
贡献
创建账号
登录
命名空间
页面
讨论
大陆简体
不转换
简体
繁體
大陆简体
香港繁體
澳門繁體
大马简体
新加坡简体
臺灣正體
查看
阅读
编辑
查看历史
更多
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
工具
链入页面
相关更改
特殊页面
页面信息