- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
一般来说,按照每个寄存器的用途编写 x86 汇编代码是否有必要或更容易?
x86 体系结构中的每个寄存器最初都设计为具有特殊用途,但现代编译器似乎并不关心它们的使用(除非在某些特殊条件下,例如 REP MOV 或 MUL)。
那么,根据每个寄存器的用途,代码会更容易或更优化吗?(不管与某些寄存器相同的特殊指令(或编码)如何)
例如(我可以改用 REP MOVSB 或 LODSB STOSB,但只是为了演示):
第一个代码:
LEA ESI,[AddressOfSomething]
LEA EDI,[AddressOfSomethingElse]
MOV ECX,NUMBER_OF_LOOP
LoopHere:
MOV AL,[ESI]
ADD AL,8
MOV [EDI],AL
ADD ESI,1
ADD EDI,1
CMP AL,0
JNZ LoopHere
TheEnd:
;...
第二个代码:
LEA ECX,[AddressOfSomething]
LEA EDX,[AddressOfSomethingElse]
MOV EBX,NUMBER_OF_LOOP
LoopHere:
MOV AL,[ECX]
ADD AL,8
MOV [EDX],AL
ADD ECX,1
ADD EDX,1
CMP AL,0
JNZ LoopHere
TheEnd:
;...
我使用的编译器--Visual Studio 2015在做这样的任务时通常使用第二种方法,它不使用寄存器取决于它的目的,相反,编译器只根据它的目的选择使用什么寄存器“ volatile ”或“非 volatile ”特征(调用函数后)。正因为如此,所有高级程序设计语言编程的软件反汇编都采用第二种方法。
另一个有趣的事实是,在 ARM 语言中,GPR 都是同一个用途,被命名为 R0-R7,这意味着用它编码时,代码会更类似于 2nd code。
总而言之,我认为这两个代码使用相同的指令,因此无论我使用什么寄存器,它都应该具有相同的速度。但我是对的吗?哪种代码更容易编码?
最佳答案
以下各寄存器的用途主要实现:
代码密度
例如使用 A
register1 通常会减少移动、算术、逻辑和 IO2 等常见操作的代码大小。
使用 C
注册计数让你利用 jcxz
指令族,避免显式比较。
movsd
和类似的是非常“密集”的指令,它们执行复杂的操作,否则将需要大量代码。
但是code density doesn't mean "faster"由于 x86 显然是 CISC,执行复杂指令可能比等效的一系列更简单指令花费更多时间3。
可读性
像rep movsd
这样的指令实际上是一种“高级”编码循环的方式,可将数据从源移动到目的地。
解析循环
push eax
pushf
.loop:
mov eax, DWORD [esi]
mov DWORD [es:edi], eax
add esi, 4*(1-D*2)
add edi, 4*(1-D*2)
dec ecx
jnz .loop
popf
pop eax
要困难得多。
地道编程
SP
的使用因为堆栈指针由许多指令( call
、 ret
、 push
、 ...)承担。
可以避免使用 SP
作为堆栈指针,但它不会很惯用(也不高效)。
更少的数据移动
在实模式下,只有少数寄存器可以用作基址(其中之一是 B
寄存器)。
将地址保存在 B
中从一开始就避免将它们移入其中。尽管寄存器-寄存器移动如今不需要执行单元,但它们使源代码更难阅读4。
今天大多数惯用的寄存器用法都放宽了5,因为太多的特定用途寄存器减少了编译器可以做的优化(并且溢出到堆栈上是昂贵的)。
CPU 非常复杂,如果您想编写速度代码,那么您应该只考虑速度指标。惯用的寄存器用法不是其中之一,一方面是 there is not a single A
, B
or C
register在微架构级别,程序员看到的“注册”只是一个人类概念(好吧,也是一个前端概念)。
1 以 AL、AX、EAX、RAX 形式br/>2 mov A, [mem]
使用操作码 A0 或 A1,而 mov B, [mem]
使用 8A 1E 或 8B 1E。 add
也是如此和类似的。 in
, out
, div
, mul
强制使用 A
.
3 但不是抓取和解码。
4 数据移入寄存器是否有等效的“意大利面条代码”?
5 例如考虑各种寻址模式或imul
说明
关于c++ - 按照每个通用寄存器的用途对 x86 程序集进行编码是否有必要或更容易,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39629753/
XML可以应用于 WEB 开发的许多方面,常用于简化数据的存储和共享 XML 把数据从 HTML 分离 现在的HTML 文档一般都是显示动态数据,每当数据改变时将花费大量的时间来编辑 HTML
在类(class)(方案)中,我们最近学习了允许函数接受任意数量参数的语法,例如; (define len (lambda args (length args))) >(len 1 2 3
在 redis-cli 中执行 info 命令时,会列出与该服务器相关的所有信息。 “evicted_keys”的目的是什么? 最佳答案 Redis 可以配置为根据需要自动清除键。如果这样配置,red
golang 空结构体 struct{} 可以用来节省内存 ? 1
有人可以解释一下资源文件夹中的 Info.plist 是什么吗?我如何在我的应用程序中使用它?提前致谢。 最佳答案 您可以在Info.plist文件中为所有类型的设备指定不同的常规资源和应用程序配置,
我需要减小可执行文件的大小,并且经常在我的可执行文件中将某些“不必要的” uses占用一定的大小。 例如: Unit1连接到Unit2,但是两个单元的导入为“ System.SysUtils”。 然后
我是 OOP 的新手。虽然我了解多态是什么,但我无法真正使用它。我可以有不同名称的函数。为什么我应该尝试在我的应用程序中实现多态性。 最佳答案 在严格类型化的语言中,多态性对于拥有不同类型对象的列表/
Possible Duplicate: What is the difference between a delegate and events? Possible Duplicate: Differ
这个问题在这里已经有了答案: Custom index.html javadoc page? (2 个答案) 关闭 7 年前。 我使用的是eclipse。一般情况下我们可以使用javadoc.exe
你能解释一下吗ValidateAntiForgeryToken目的并向我展示有关 MVC 4 中的 ValidateAntiForgeryToken 的示例? 我找不到任何解释此属性的示例? 最佳答案
我正在学习 RxSwift 并试图了解 Observable 和 PublishSubject aka Sequence 之间的主要区别。 据我了解,Sequences/PublishesSubjec
有时有人说,在使用 Azure 表时,实际上存在第三个关键分区数据 - 表名称本身。 我在执行分段查询时注意到 TableContinuationToken 有一个 NextTableName 属性。
在Apple提供的aurioTouch项目中,听说在performRender()函数下的AudioController文件中的AudioBufferList ioData携带了mic到音频播放器的音
MSDN 文档没有详细解释它的用途。 由于它是可选的,我几乎假设它类似于某种元数据。 我现在如何看待它,我想用它来为特定用户指定缓存,例如: new CacheItem(key: "keyName",
我正在学习 browserify,我正在尝试用它做两件基本的事情: 转换(通过 shim)非 CommonJS 模块以实现易用性和依赖跟踪 捆绑项目特定的库 我找到了一个工作流程,说明如何使用 Gul
我通过按 CTRL + C 访问 eix 1.8.2 的 Break 菜单。它看起来像这样: BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
在 codeLabs 教程(Android - Kotlin - Room with a View)中,他们使用“viewModelScope.launch(Dispatchers.IO)”来调用插入
我通过按 CTRL + C 访问 eix 1.8.2 的 Break 菜单。它看起来像这样: BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
请耐心等待,因为我没有太多地使用压缩算法,所以这对你们中的一些人来说可能是显而易见的。当某些流媒体视频开始滞后时,我总是注意到这一点。当我看到这个问题时我才意识到我很好奇: Twitter image
关闭。这个问题是opinion-based 。目前不接受答案。 想要改进这个问题吗?更新问题,以便 editing this post 可以用事实和引文来回答它。 . 已关闭 3 年前。 Improv
我是一名优秀的程序员,十分优秀!