2013-05-07 5 views
5

मैं फिर से असेंबली भाषा करना सीख रहा हूं, और अब तक की एकमात्र समस्या सी को कॉल कर रही है। मेरे पास पुस्तक 32 बिट तक है, और मैं 64 बिट में काम कर रहा हूं। स्पष्ट रूप से कॉलिंग सम्मेलनों में एक बड़ा अंतर है, और http://www.x86-64.org/documentation साइट डाउन है। तो कुछ खुदाई/परीक्षण के बाद, सी में डमी कार्यक्रमों को संकलित करने और इस पर 3 दिन खर्च करने के बाद मैंने सोचा कि अगर मैं किसी और की मदद करता हूं तो मैं अपने निष्कर्ष पोस्ट करूंगा।प्रिंटफ को 64 बिट एएसएम से कॉल करते समय पैरा कैसे पारित किए जाते हैं?

क्या आरएक्स को फ्लोट गिनती दी जानी चाहिए? स्टैक पैडिंग "छाया स्थान" 16 या 32 बिट्स है? क्या यह मैक्रो छोटे कार्यक्रमों के लिए पारित स्टैक को संरेखित करने के लिए है? मुझे पता है कि आप कोड को एनओपी-पैड संरेखित कर सकते हैं, मुझे स्टैक फ्रेम के बारे में निश्चित नहीं था।

; pf.asm compiled with 'nasm -o pf.o -f elf64 -g -F stabs' 
; linked with 'gcc -o pf pf.o' 
; 64-bit Bodhi (ubuntu) linux 

%include "amd64_abi.mac" 
[SECTION .data] 
First_string: db "First string.",10,"%s", "%d is an integer. So is %d",10 
       db "Floats XMM0:%5.7f XMM1:%.6le XMM2:%lg",10,0 
Second_String: db "This is the second string... %s's are not interpreted here.",10 
       db " Neither are %d's nor %f's. 'Cause it is a passed value.", 10, 0 
; Just a regular string for insert. 
[SECTION .bss] 
[SECTION .text] 
EXTERN printf 
GLOBAL main 
main: 
_preserve_64AMD_ABI_regs ; Saves RBP, RBX, R12-R15 
mov rdi, First_string ; Start of string to be formatted. Null terminated 
mov rsi, Second_String ; String addy of first %s in main string. Not interpretted 
mov rcx, 0456   ; Second Integer (Register is specific for ordered arguments.) 
mov rdx,; First integer (Order of assignment does not matter.) 
         ; Order of Integer/Pointer Registers: 
         ; $1:RDI $2:RSI $3:RDX $4:RCX $5:R8 $6:R9 

mov rax,0AABBCCh   ; Test value to be stored in xmm0 
cvtsi2sd xmm0, rax  ; Convert quad to scalar double 
mov rax,003333h   ; Test value to be stored in xmm1 
cvtsi2sd xmm1, rax  ; Convert quad to scalar double 
cvtsi2sd xmm2, rax  ; Convert quad to scalar double 
divsd xmm2, xmm0  ; Divide scalar double 

sub rsp, 16    ; Allocates 16 byte shadow memory 
_prealign_stack_to16 ; Move to the lower end 16byte boundry (Seg-Fault otherwise) 
; mov rax, 3    ; Count of xmm registers used for floats. ?!needed?! 
Before_Call: 
call printf    ; Send the formatted string to C-printf 
_return_aligned_stack ; Returns RSP to the previous alignment 
add rsp, 16    ; reallocate shadow memory 

_restore_64AMD_ABI_regs_RET 
; Ends pf.asm 

; amd64_abi.mac 
; Aligns stack (RSP) to 16 byte boundry, padding needed amount in rbx 
%macro _preserve_64AMD_ABI_regs 0 
push rbp 
mov rbp, rsp 
push rbx 
push r12 
push r13 
push r14 
push r15 
%endmacro 

%macro _restore_64AMD_ABI_regs_RET 0 
pop r15 
pop r14 
pop r13 
pop r12 
pop rbx 
mov rsp, rbp 
pop rbp 
ret 
%endmacro 

%macro _prealign_stack_to16 0 
mov rbx, 0Fh   ; Bit mask for low 4-bits 10000b = 16 :: 01111b = 15b 
and rbx, rsp   ; get bits 0-3 into rbx 
sub rsp, rbx   ; remove them from rsp, rounding down to multiple of 16 (10h) 
%endmacro 

; De-aligns stack (RSP)from 16 byte boundry using saved rbx offset 
%macro _return_aligned_stack 0 
add rsp, rbx 
%endmacro 

आउटपुट: पहली स्ट्रिंग। यह दूसरी स्ट्रिंग है ...% s का अर्थ यहां नहीं लिया गया है। न तो% d's और न ही% f है। 'क्योंकि यह एक पारित मूल्य है। 123 एक पूर्णांक है। 11189196.0000000 XMM1: 1.310700e +04 XMM2: 0,0011714

संसाधन: सिस्टम वी ABI v0.96: http://www.uclibc.org/docs/psABI-x86_64.pdf (यह x86-64.org साइट नीचे है पर उपलब्ध नहीं है) विधानसभा भाषा तो 456 तैरता XMM0 है क्रमशः। जेफ डंटमैन अध्याय 12 इंटेल 64-बिट निर्देश सेट। http://www.intel.com/content/www/us/en/processors/architectures-software-developer-manuals.html

+2

स्पष्ट दृष्टिकोण पहले सी में कोड लिखना है और एक सी संकलक असेंबली उत्पन्न करता है। यह कभी गलत नहीं होगा। –

उत्तर

6

हां, RAX (वास्तव में AL) XMM रजिस्टरों का उपयोग किया जाना चाहिए।

आपका स्टैक संरेखण कोड अधिक जटिल है, आमतौर पर आप केवल AND rsp, -16 करते हैं। इसके अलावा, स्टैक संरेखण आमतौर पर केवल एक बार किया जाता है (आमतौर पर main की शुरुआत में) और फिर इसे उचित रूप से rsp समायोजित करके बनाए रखा जाता है।

SYSV एबीआई छाया स्थान का उपयोग नहीं करता है (यह माइक्रोसॉफ्ट कन्वेंशन है) इसके बजाय यह "लाल क्षेत्र" का उपयोग करता है, लेकिन यह कॉलिंग अनुक्रम को प्रभावित नहीं कर रहा है।

अद्यतन ढेर संरेखण के बारे में:

कार्यों कि पहले से ही गठबंधन हो RSP (आम तौर पर main के अलावा सब कुछ) में, आप बस यकीन है कि बदले में किसी भी बुलाया कार्यों RSP मिलता है कि 16

की एक बहु से बदल गया है बनाने

यदि आप मानक फ्रेम पॉइंटर का उपयोग कर रहे हैं, तो आपके फ़ंक्शन PUSH RBP से शुरू होते हैं, तो आपको केवल यह सुनिश्चित करना होगा कि आप 16 (यदि आवश्यक हो) के गुणकों में स्थान आवंटित करते हैं, जैसे:

push rbp 
mov rbp, rsp 
sub rsp, n*16 
... 
mov rsp, rbp 
pop rbp 
ret 

अन्यथा, आप RIP के 8 बाइट्स ढेर पर डाल की भरपाई के लिए (के रूप में आप सही ढंग से है कि अपनी टिप्पणी में बताया) होगा:

sub rsp, n*16+8 
... 
add rsp, n*16+8 
ret 

उपरोक्त दोनों ही लागू होते हैं, तो आप कॉल अन्य कार्यों, जो पत्ते के कार्यों में हैं आप जो भी चाहें कर सकते हैं।इसके अलावा, लाल क्षेत्र कि मैंने पहले बताया, पत्ती कार्यों में उपयोगी है क्योंकि आप स्पष्ट आवंटन बिना ढेर सूचक के तहत 128 बाइट्स का उपयोग कर सकते हैं, तो आप अर्थ बिल्कुल RSP समायोजित करने के लिए की जरूरत नहीं है:

; in leaf functions you can use memory under the stack pointer 
; (128 byte red zone) 
mov [rsp-8], rax 
+0

अच्छा, यह बहुत उपयोगी है। इसलिए जब भी मैं शुरुआती संरेखण के बाद धक्का देता हूं, तो इसे करें; उप आरएसपी, 10 एच; mov [आरएसपी], $ मूल्य ... फिर कॉल के बाद बस इसे वापस जोड़ें? – DouglasCodes

+0

कॉल के ठीक पहले सभी कॉल 16 पर गठबंधन किए जाएंगे? तो फिर कॉल आरआईपी को ढेर पर धक्का देता है। इसे 8 तक समायोजित करने की आवश्यकता है ... इसलिए मैं शुरुआत में और 'आरएसपी, -16' और आरईटी से पहले आरएसपी, 8' जोड़ सकता हूं। सही बात? – DouglasCodes

+0

उत्तर अद्यतन किया गया। – Jester

संबंधित मुद्दे