ADDS Rn, #1ADDS Rd, Rn, #1
ARM 檔案指定在第一條指令中,如果 Rd 是可選的并且如果省略 Rd 等于 Rn。所以編譯時兩條指令應該是相同的。但是我們的編譯器正在生成:
二進制0x3F01和SUBS R7,#1
二進制0x1E7F _SUBS R7,R7,#1
使用指令解碼 0x3F01 等于 001 11 111 00000001 001
001 -> 加/減/比較/立即移動
11 -> 操作碼減去 imm
111 -> R7
00000001 -> 值 1
使用指令解碼
0x1E7F 等于 000111 1 001 111 111
000111 -> 加/減暫存器
1 -> 立即減去
001 -> 值 1
111 -> R7
111 -> R7
所以兩條指令都在執行相同的操作。知道為什么編譯器可能會生成不同的二進制檔案嗎?
uj5u.com熱心網友回復:
ARM 檔案指定在第一條指令中,如果 Rd 是可選的并且如果省略 Rd 等于 Rn。所以編譯時兩條指令應該是相同的。
首先,您應該注意有兩種不同的 ARM 指令集:“傳統”32 位指令集和“Thumb”指令集。
您的 CPU 顯然使用“Thumb”指令集。
許多關于 ARM 指令集的陳述都參考了“傳統”指令集。
在傳統指令集中,兩種形式 (SUBS R7, #1和SUBS R7, R7, #1) 確實會產生相同的指令:0xE2577001。
但是,在“Thumb”指令集中,有兩種不同的編碼:
SUBS Rd, Rn, #imm允許為兩個不同的暫存器指定Rd,Rn但只允許在 0...7 范圍內的立即數。
SUBS Rd, #imm僅允許單暫存器形式,但允許 0...255 范圍內的立即數。
但是,SUBS R7, R7, #1并且SUBS R7, #1做同樣的事情。
知道為什么編譯器可能會生成不同的二進制檔案嗎?
如果您顯式鍵入SUBS R7, R7, #1或SUBS R7, #1在匯編代碼中?
因為你也可以輸入SUBS R7, R6, #1or SUBS R7, #90。在這些情況下,編譯器必須以不同的方式處理這兩種變體!
所以它總是以不同的方式處理這兩種變體,因為它會更加努力地檢查兩個暫存器是否相等或檢查立即數是否小于 8。
uj5u.com熱心網友回復:
它是一個匯編器而不是編譯器。匯編語言特定于匯編器而不是目標。匯編器是否允許 subs r7,#1 在功能上等于 subs r7,r7,#1,特別是如果兩個或三個暫存器與一個暫存器有不同的編碼,則取決于匯編器的作者,而不是處理器 IP也不是芯片供應商。
我們以 gnu 匯編器為例:
.thumb
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
.syntax unified
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
.thumb2
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
從這個版本開始
arm-none-eabi-as --version
GNU assembler (2.34-4ubuntu1 13ubuntu1) 2.34
Copyright (C) 2020 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `arm-none-eabi'.
arm-none-eabi-as so.s -o so.o
so.s: Assembler messages:
so.s:20: Error: unknown pseudo-op: `.thumb2'
所以需要洗掉 .thumb2 的東西(匯編語言特定于匯編器而不是目標,你使用的是什么匯編器和版本?)
.thumb
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
.syntax unified
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
Disassembly of section .text:
00000000 <.text>:
0: 3f01 subs r7, #1
2: 3f01 subs r7, #1
4: 1e77 subs r7, r6, #1
6: 3f01 subs r7, #1
8: 3f01 subs r7, #1
a: 1e77 subs r7, r6, #1
c: f1a7 0701 sub.w r7, r7, #1
10: f1a7 0701 sub.w r7, r7, #1
14: f1a6 0701 sub.w r7, r6, #1
18: 3f01 subs r7, #1
1a: 3f01 subs r7, #1
1c: 1e77 subs r7, r6, #1
所以它盡可能地使用了 0x3F01。還有另一種風味,當它有兩個不同的暫存器時。
該工具仍然支持世界的預統一語法狀態,無論出于何種原因(匯編語言特定于該工具而不是目標),他們選擇支持帶有后綴的 sub。實際上,我很驚訝,因為如果您嘗試基于 add 或 subs 等構建 thumb 指令,不同版本的 gnu 匯編程式會抱怨......并且您必須使用 add 和 sub 代替。在這種情況下,它容忍了潛艇。
readelf 的尾部顯示了這一點,如果未指定,則與默認目標有關。
Attribute Section: aeabi
File Attributes
Tag_CPU_arch: v6T2
Tag_THUMB_ISA_use: Thumb-2
這看起來像 arm11 對吧?一個全尺寸的 ARM。讓我們用 armv6-m 試試
.cpu cortex-m0
.thumb
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
.syntax unified
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
不開心
so.s: Assembler messages:
so.s:16: Error: lo register required -- `sub r7,#1'
so.s:17: Error: lo register required -- `sub r7,r7,#1'
so.s:18: Error: lo register required -- `sub r7,r6,#1'
.cpu cortex-m0
.thumb
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
.syntax unified
subw r7,#1
subw r7,r7,#1
subw r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
so.s: Assembler messages:
so.s:16: Error: selected processor does not support `subw r7,#1' in Thumb mode
so.s:17: Error: selected processor does not support `subw r7,r7,#1' in Thumb mode
so.s:18: Error: selected processor does not support `subw r7,r6,#1' in Thumb mode
這更清楚了,armv6-m 不支持根據 armv7-m 架構參考手冊的 T1 編碼顯示您正在談論的帶有兩個暫存器的 0x1Exx 編碼,而該檔案中的 T2 是 0x38xx 一個。thumb2 編碼是 armv7-m 而不是 armv6-m(armv6-m 在“所有 thumb 變體”中添加了幾十個。armv7-m 添加了大約 150 個 thumb2 擴展,體驗非常不同。
.cpu cortex-m7
.thumb
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
.syntax unified
sub r7,#1
sub r7,r7,#1
sub r7,r6,#1
subs r7,#1
subs r7,r7,#1
subs r7,r6,#1
然后生成:
Disassembly of section .text:
00000000 <.text>:
0: 3f01 subs r7, #1
2: 3f01 subs r7, #1
4: 1e77 subs r7, r6, #1
6: 3f01 subs r7, #1
8: 3f01 subs r7, #1
a: 1e77 subs r7, r6, #1
c: f1a7 0701 sub.w r7, r7, #1
10: f1a7 0701 sub.w r7, r7, #1
14: f1a6 0701 sub.w r7, r6, #1
18: 3f01 subs r7, #1
1a: 3f01 subs r7, #1
1c: 1e77 subs r7, r6, #1
File Attributes
Tag_CPU_name: "Cortex-M7"
Tag_CPU_arch: v7E-M
Tag_CPU_arch_profile: Microcontroller
Tag_THUMB_ISA_use: Thumb-2
所以再次使用 0x3f01 編碼。
匯編語言特定于工具而不是目標。匯編語言作者可以自由選擇等效指令。當年的一位作者甚至聲稱編碼模式的選擇是這樣的,他可以確定您是否使用了他的匯編程式(它是共享軟體,如果您沒有付費......我可以告訴...... .)
手術
if ConditionPassed() then
EncodingSpecificOperations();
(result, carry, overflow) = AddWithCarry(R[n], NOT(imm32), '1');
R[d] = result;
if setflags then
APSR.N = result<31>;
APSR.Z = IsZeroBit(result);
APSR.C = carry;
APSR.V = overflow;
至少根據我手頭的 armv7-m 架構參考手冊,在功能上它們都是相同的,無論是具有一個或兩個暫存器和不同即時規則的兩個全拇指變體版本以及 thumb2 擴展。
匯編語言特定于工具而不是目標。工具作者可以自由定義匯編語言,包括選擇等效編碼的自由,即使它與用戶提供的語法不匹配(工具支持的語法不一定與 IP 供應商檔案相關,它是作者完全選擇。pickle orange,apple,#1 是完全有效的語法,您不會有很多用戶,但只要它產生正確的指令就沒有問題)(IP 供應商檔案位于他們自己的內部工具程式集之間語言(由工具而非目標定義)或任何匯編程式不支持的通用語言(發生這種情況)。
.thumb、.thumb2 等都是特定工具語言的一部分,這些和其他指令對工具的作用是特定于工具的,而不是對所有 ARM 代碼通用的,當然不是所有各種 ARM 指令集的所有 ARM 代碼和版本。(了解ARM thumb指令集有幾個不同的版本,很少被參考,但是當你看到它時,基本上每一個下一代架構全尺寸或MCU市場,都有一個新版本)。
uj5u.com熱心網友回復:
我發現了編譯器(用于 ARM Cortex-M3 的 Greenhills 編譯器)如何生成3F01和1E7F二進制檔案。
{
asm(".thumb");
0x2008af8 main: b500 PUSH {LR}
0x2008afa main 0x2: b081 SUB SP, #4
asm("SUBS R7, #1");
0x2008afc main 0x4: 3f01 SUBS R7, #1
asm("SUBS R7, R7, #1");
0x2008afe main 0x6: 1e7f SUBS R7, R7, #1
asm(".thumb2");
asm("SUBS R7, #1");
0x2008b00 main 0x8: 1e7f SUBS R7, R7, #1
asm("SUBS R7, R7, #1");
0x2008b02 main 0xa: 1e7f SUBS R7, R7, #1
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/430135.html
上一篇:兩個陣列的減法并將結果存盤在第三個陣列中,并以匯編語言8086在螢屏上顯示結果
下一篇:為什么堆疊幀按24位元組對齊?
