मैं जटिल अप्रत्यक्ष एड्रेसिंग मोड से सरल अप्रत्यक्ष एड्रेसिंग मोड टुकड़ों में उदाहरणों को बदलने पर काम कर रहा हूं। हालांकि, मैं आधारित मोड से एक उदाहरण में आया हूं, मैं "रूपांतरित" करने में असमर्थ हूं।

movzbl  string+8, %eax

मैंने यह कोशिश की है:

addl    $8, string
movzbl  string, %eax

इस कोड को संकलित करने के बाद, त्रुटि संदेश पॉप अप होता है।

0
Biggy Poopa 30 अप्रैल 2018, 15:29

2 जवाब

सबसे बढ़िया उत्तर
lea string, %eax
add $8, %eax
movzbl (%eax), %eax

लेकिन movzbl string+8, %eax "जटिल एड्रेसिंग मोड" नहीं है, इसे असेंबलर/लिंकर द्वारा हल किया जाता है।

1
mevets 30 अप्रैल 2018, 16:12

string+8 आधारित-इंडेक्स एड्रेसिंग मोड नहीं है। यह बिना आधार रजिस्टर के एक disp32 निरपेक्ष पते पर इकट्ठा होता है। +8 को असेंबल/लिंक समय पर हल किया जाता है। (देखें स्मृति की सामग्री को संदर्भित करना स्थान। (x86 एड्रेसिंग मोड))

movzbl string+8, %eax एक ही एड्रेसिंग मोड (ModR/M बाइट) के साथ मशीन कोड को movzbl string, %eax के रूप में असेंबल करता है, बस एक अलग disp32 विस्थापन। देखें C++ लिंकिंग व्यवहार में कैसे काम करता है? कुछ के लिए इस बारे में विवरण कि कैसे कोडांतरण + लिंकिंग +8 का ख्याल रखता है ताकि रन टाइम पर कोई अतिरिक्त काम न हो।


आप ऐसा कर सकते हैं, क्योंकि string+8 एड्रेसिंग मोड नहीं है, यह एक लिंक-टाइम स्थिरांक है जिसे आप तत्काल ऑपरेंड के रूप में उपयोग कर सकते हैं

mov     $string+8, %edx
movzbl  (%edx), %eax

lea के बजाय mov का उपयोग करने से यह बात स्पष्ट हो जाती है, IMO। एक रजिस्टर में एक स्थिर पता डालने के लिए lea का उपयोग करने का एकमात्र कारण x86-64 में है जब आप इसे स्थिति-स्वतंत्र कोड (या निम्न 2 GiB के बाहर कोड के लिए RIP- सापेक्ष पते के लिए उपयोग कर सकते हैं, जैसे ओएस एक्स)। जैसे lea string+8(%rip), %rdx.


असेंबल टाइम के बजाय रन-टाइम पर सबसे बेकार सामान करने का सबसे अधिक जटिल तरीका होगा

mov     $string, %edx
add     $8, %edx
movzbl  (%edx), %eax

मुझे लगता है कि lea का उपयोग करना और भी अधिक जटिल होगा, या आप inc 8 बार कर सकते हैं, या inc को 8 बार लूप लिख सकते हैं, लेकिन यह एक अलग तरीके से अधिक जटिल है।


उदाहरण के लिए, यह स्रोत दिया गया है:

.globl _start
_start:
   mov  $string, %eax
   mov  $string+8, %eax
   movzbl string+8, %eax

.section .rodata
string:

मैं gcc -m32 foo.S -c के साथ इकट्ठा हुआ और objdump -drwC foo.o से अलग हुआ (विकल्प -r स्थानांतरण दिखाता है):

foo.o:     file format elf32-i386
Disassembly of section .text:
00000000 <_start>:
   0:   b8 00 00 00 00          mov    $0x0,%eax        1: R_386_32     .rodata
   5:   b8 08 00 00 00          mov    $0x8,%eax        6: R_386_32     .rodata
   a:   0f b6 05 08 00 00 00    movzbl 0x8,%eax         d: R_386_32     .rodata

वास्तविक पतों के बजाय, 0 और 0x8 प्लेसहोल्डर उस स्थानांतरण के लिए प्रतीक मान से ऑफ़सेट होते हैं। वे string के बजाय ऑब्जेक्ट फ़ाइल के .rodata अनुभाग के विरुद्ध हैं क्योंकि मैंने उस प्रतीक को वैश्विक बनाने के लिए .globl _string का उपयोग नहीं किया था।

अगर मैं gcc -static -m32 -nostdlib foo.S के साथ + लिंक इकट्ठा करता हूं और अलग करता हूं, तो मुझे मिलता है:

 8048098:       b8 a9 80 04 08          mov    $0x80480a9,%eax
 804809d:       b8 b1 80 04 08          mov    $0x80480b1,%eax
 80480a2:       0f b6 05 b1 80 04 08    movzbl 0x80480b1,%eax

ध्यान दें कि movzbl (छोटे-एंडियन में) के अंतिम 4 बाइट्स में लोड करने के लिए पूर्ण पता कैसे है, वही 4-बाइट मान जो b8 ऑपोड के लिए तत्काल है (mov- imm32-to-eax)।

यह भी देखें कि कैसे string और string+8 का परिणाम अलग-अलग एड्रेस बाइट्स में होता है लेकिन एक ही ओपकोड।

2
Peter Cordes 30 अप्रैल 2018, 17:20