Windows 64 ABI,如果我不调用 windows API,寄存器使用正确吗?
Windows 64 ABI, correct register use if i do NOT call windows API?
正如我在另一个问题中向我建议的那样,我检查了 windows ABI 并且我对如果我不调用 windows [=51] 我能做什么和不能做什么感到有点困惑=]我自己。
我的情况是我正在编写 .NET 程序并且需要 asm 中的一小段代码以特定处理器为目标,用于对数组进行大量多通道处理的时间关键代码部分。
在https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
查看ABI中的寄存器信息时
如果我
,我对适用于我的情况感到有点困惑
1) 不要从 asm 代码中调用 windows API
2) 不要 return 值并采用单个参数。
这是我的理解,我的理解是否正确?
RAX:我可以在不保留它的情况下覆盖它,因为该函数不需要 return 值
RCX:我需要保留它,因为这是传递单个 int 参数的地方,然后我可以覆盖它而不是恢复它
RDX/R8/R9:不应初始化,因为我的方法中没有此类参数,我可以覆盖它们而不是恢复它们
R10/R11 : 我可以覆盖那些而不保存它们,如果调用者需要它他负责保存它们
R12/R13/R14/R15/RDI/RSI/RBX:我可以覆盖它们,但我首先需要保存它们(或者如果我不调用 windows API,我可以不保存它们吗?)
RBP/RSP : 我假设我不应该碰那些?
如果是这样,我是否正确认为这是处理此问题的正确方法(如果我不关心保存数据所花费的时间并且需要尽可能多的可用寄存器)?或者有没有办法使用更多的寄存器?
; save required registers
push r12
push r13
push r14
push r15
push rdi
push rsi
push rbx
; my own array processing code here, using rax as the memory address passed as the first parameter
; safe to use rax rbx rcx rdx r8 r9 r10 r11 r12 r13 r14 r15 rdi rsi giving me 14 64bit registers
; 1 for the array address 13 for processing
; should not touch rbp rsp
; restore required registers
pop rbx
pop rsi
pop rdi
pop r15
pop r14
pop r13
pop r12
TL;DR:如果您需要标记为保留的寄存器,push/pop 以正确的顺序排列它们。使用您的代码,您可以毫无问题地使用您提到的那 14 个寄存器。如果保留它,您可能会接触 RBP,但基本上永远不要接触 RSP。
如果您调用 Windows API 确实很重要,但不是我假设您认为的那样。 ABI 说明您必须保留哪些寄存器。保留信息意味着 caller 知道有些寄存器你不会改变。您不需要调用任何 Windows API 函数来满足该要求。
类似的想法(是的,我知道...):这里有五叠不同颜色的便签纸。你可以使用它们中的任何一个,但是如果你需要红色或蓝色的,你能不能把最上面的一个放在安全的地方,当你停下来的时候把它放回去,因为我需要它们上面的 phone 数字。其他颜色我不在乎,它们只是草稿纸,我已经在其他地方写了信息。
所以如果你调用一个外部函数你知道没有函数会改变标记为[=22的寄存器的值=]保留。任何其他寄存器可能更改它们的值并且你必须确保你那里没有任何需要保留的东西。
并且当调用你的函数时,调用者期望相同:如果他们将一个值放入保留的寄存器中,它将调用后具有相同的值。但是任何非保留的寄存器都可以是任何东西,如果需要保留它们,它们将确保存储这些值。
return 值寄存器您可以随意使用。如果函数没有 return 值,则调用者不得期望它具有任何特定值,也不期望它保留其值。
您只需保留您使用的寄存器。如果您不使用所有这些,则无需全部保留。
您可以自由使用RAX
、RCX
、RDX
、R8
、R9
、R10
和R11
.后两者必须由 调用者 保留,如有必要,而不是由您的函数保留。
大多数时候,这些寄存器(或它们的子寄存器,如 EAX
)足以满足我的需要。我几乎不需要更多。
当然,如果其中任何一个(例如 RCX
)包含您的函数的参数,您可以根据需要自行保留它们。你如何做到这一点也取决于你。但是如果你 push
他们,请确保某处有相应的 pop
。
使用 This MSDN page 作为指南。
正如我在另一个问题中向我建议的那样,我检查了 windows ABI 并且我对如果我不调用 windows [=51] 我能做什么和不能做什么感到有点困惑=]我自己。
我的情况是我正在编写 .NET 程序并且需要 asm 中的一小段代码以特定处理器为目标,用于对数组进行大量多通道处理的时间关键代码部分。
在https://msdn.microsoft.com/en-us/library/9z1stfyw.aspx
查看ABI中的寄存器信息时如果我
,我对适用于我的情况感到有点困惑1) 不要从 asm 代码中调用 windows API
2) 不要 return 值并采用单个参数。
这是我的理解,我的理解是否正确?
RAX:我可以在不保留它的情况下覆盖它,因为该函数不需要 return 值
RCX:我需要保留它,因为这是传递单个 int 参数的地方,然后我可以覆盖它而不是恢复它
RDX/R8/R9:不应初始化,因为我的方法中没有此类参数,我可以覆盖它们而不是恢复它们
R10/R11 : 我可以覆盖那些而不保存它们,如果调用者需要它他负责保存它们
R12/R13/R14/R15/RDI/RSI/RBX:我可以覆盖它们,但我首先需要保存它们(或者如果我不调用 windows API,我可以不保存它们吗?)
RBP/RSP : 我假设我不应该碰那些?
如果是这样,我是否正确认为这是处理此问题的正确方法(如果我不关心保存数据所花费的时间并且需要尽可能多的可用寄存器)?或者有没有办法使用更多的寄存器?
; save required registers
push r12
push r13
push r14
push r15
push rdi
push rsi
push rbx
; my own array processing code here, using rax as the memory address passed as the first parameter
; safe to use rax rbx rcx rdx r8 r9 r10 r11 r12 r13 r14 r15 rdi rsi giving me 14 64bit registers
; 1 for the array address 13 for processing
; should not touch rbp rsp
; restore required registers
pop rbx
pop rsi
pop rdi
pop r15
pop r14
pop r13
pop r12
TL;DR:如果您需要标记为保留的寄存器,push/pop 以正确的顺序排列它们。使用您的代码,您可以毫无问题地使用您提到的那 14 个寄存器。如果保留它,您可能会接触 RBP,但基本上永远不要接触 RSP。
如果您调用 Windows API 确实很重要,但不是我假设您认为的那样。 ABI 说明您必须保留哪些寄存器。保留信息意味着 caller 知道有些寄存器你不会改变。您不需要调用任何 Windows API 函数来满足该要求。
类似的想法(是的,我知道...):这里有五叠不同颜色的便签纸。你可以使用它们中的任何一个,但是如果你需要红色或蓝色的,你能不能把最上面的一个放在安全的地方,当你停下来的时候把它放回去,因为我需要它们上面的 phone 数字。其他颜色我不在乎,它们只是草稿纸,我已经在其他地方写了信息。
所以如果你调用一个外部函数你知道没有函数会改变标记为[=22的寄存器的值=]保留。任何其他寄存器可能更改它们的值并且你必须确保你那里没有任何需要保留的东西。
并且当调用你的函数时,调用者期望相同:如果他们将一个值放入保留的寄存器中,它将调用后具有相同的值。但是任何非保留的寄存器都可以是任何东西,如果需要保留它们,它们将确保存储这些值。
return 值寄存器您可以随意使用。如果函数没有 return 值,则调用者不得期望它具有任何特定值,也不期望它保留其值。
您只需保留您使用的寄存器。如果您不使用所有这些,则无需全部保留。
您可以自由使用RAX
、RCX
、RDX
、R8
、R9
、R10
和R11
.后两者必须由 调用者 保留,如有必要,而不是由您的函数保留。
大多数时候,这些寄存器(或它们的子寄存器,如 EAX
)足以满足我的需要。我几乎不需要更多。
当然,如果其中任何一个(例如 RCX
)包含您的函数的参数,您可以根据需要自行保留它们。你如何做到这一点也取决于你。但是如果你 push
他们,请确保某处有相应的 pop
。
使用 This MSDN page 作为指南。