再來就是迴圈的輸出了,GDB是跳到+42的位址後做的事情是將RBP-0x10放入RAX內,IDA是跳到loc_1004010AB將RBP-10h放入RAX內,是做一樣的事情。
下一步就是將RAX內的值放到RDI並進行輸出了,到這邊可能會遇到一個問題是,之前明明RAX就吃不下完整的字串,並且要分兩次放入Stack中,為什麼現在一次就可以丟進RAX並且馬上就輸出了,這時候就要說明MOV和LEA的差異了,MOV是將值丟進去,而LEA是處理address的,也就是說其實在做LEA RAX,RBP-10這一步驟,是將字串的address位址給放入RAX當中,而不是將完整的字串送入RAX。
可以看到這個是LEA前的RAX資料
LEA後的RAX
接下來就可以驗證RAX裡的Address是不是指向字串
GDB和IDA都有正確的指向我們想要輸出的字串上,接下來就是將這個Address送入要輸出的puts,所以我們看下一行的暫存器變化。
這邊會發現兩個很問號的操作,第一個是為什麼是puts,第二個是為什麼IDA會跑到RCX去,在前面有提到過RCX通常會用在迴圈上的計數,應該要跑到RDI才對,RCX跟字串好像沒什麼關係。
第一個變成puts可能是因為編譯器的最佳化所導致,因為比起printf來說,puts所使用的資源更少,而在編譯器確認這個輸出很單純的時候,就可能會將其改為puts。
第二個也是編譯器所導致的,由於使用的編譯器是Cygwin,而Cygwin所使用的是Windows x64 Calling Convention 而不是我們所熟知的System V x86-64 psABI,因此會有所差異,有興趣的可以參考兩者的Document。