%macro read 1
Mov ax,3
mov bx,0
mov rcx,%1
mov dx,20
Int 80h
%endmacro

%macro print 2
Mov ax,4
mov bx,1
mov rcx,%1
mov dx,%2
Int 80h
%endmacro  

 section .Data
           len : db 0
   section .bss
       Str1 resb 20
       Str2 resb 20
   section .text
     global _start: 
          read str1 ;using macro
      mov [len],al
      lea rsi,[str1]
      lea rdi,[str2]
      mov rcx,rax
      dec rcx
      Add rsi,rcx
 loop1:
       Dec rsi
       Mov al,[rsi]
       Mov [rdi],al
       Inc rdi
       loop loop1
       print str2,[len]

     Exit: 
        mov ax,1
        Mov bx,0
        int 80h


उपरोक्त एएसएम कोड के साथ मैं एक स्ट्रिंग के विपरीत पा सकता हूं। लेकिन यहां स्ट्रिंग रजिस्टर पढ़ने के बाद Al को लेन में ले जाया जाता है लेकिन Register Al को इनिशियलाइज़ नहीं किया जाता है और rcx द्वारा कौन सा डेटा होल्ड किया जाता है, रक्स?

क्या कोई बस उपरोक्त कोड की व्याख्या कर सकता है?

0
Aashiq Otp 10 नवम्बर 2019, 13:03

1 उत्तर

सबसे बढ़िया उत्तर

स्पष्ट रूप से read RAX में लंबाई लौटाता है। यह कार्यों के लिए पूरी तरह से सामान्य है, और मैक्रो के लिए भी समझ में आता है।

इस मामले में, हाँ, यह read() जैसा कि मैन पेज बताता है, लंबाई लौटाता है। लिनक्स सिस्टम कॉल RAX में वापस आते हैं। यह अजीब तरह से अधिकतम लंबाई को 20 के रूप में हार्ड-कोड करता है।

(यह छोटी गाड़ी है क्योंकि यह केवल तभी काम करता है जब EAX, EBX, और EDX पहले से ही शून्य हों। यह 32-बिट ABI को लागू करने से पहले केवल उन रजिस्टरों के कम 16 बिट्स लिखता है। एक पते के साथ पूर्ण RCX लिखना बेकार है; int 0x80 केवल कम 32 बिट्स का उपयोग करता है। -64-बिट-कोड/46087731#46087731">यदि आप 64-बिट कोड में 32-बिट int 0x80 Linux ABI का उपयोग करते हैं तो क्या होगा?)

AL RAX का निम्न बाइट है, और यह कोड मुद्रण के लिए केवल लंबाई के निम्न बाइट को बचाता है। आईडीके वे इसे एक सामान्य व्यक्ति की तरह दूसरे रजिस्टर के बजाय मेमोरी में क्यों सहेजते हैं। विशेष रूप से जब वे आरसीएक्स में 32-बिट मान को शून्य-विस्तारित करने के लिए सामान्य mov ecx, eax के बजाय पूरी 64-बिट लंबाई को आरसीएक्स में कॉपी करते हैं।


यह भी ध्यान दें कि बाद वाला mov ax,1 (32-बिट __NR_exit) जोखिम भरा और एक बुरा विचार है; यह संभावित रूप से RAX के उच्च बाइट्स में कचरा छोड़ता है जिससे _exit(0) के बजाय -ENOSYS हो जाता है,

छोटे बफ़र आकार के साथ रीड फॉल्ट होगा (या -EFAULT वापस आने से पहले यह 4096 से अधिक लौटा सकता है, इसलिए इस मामले में RAX के केवल कम 16 बिट्स को बदलना सुरक्षित है।

जब तक read एक नकारात्मक त्रुटि कोड नहीं लौटाता; तब यह प्रोग्राम बाहर निकलने के बजाय क्रैश हो जाएगा जब अंतिम int 0x80 बाहर निकलने के बजाय -ENOSYS वापस आ जाएगा।

stdin को बंद करने के लिए इसे ./a.out <&- के साथ चलाने का प्रयास करें, जिससे -EBADF stdin से पढ़ने के लिए, फिर क्रैश हो जाए।

साथ ही, यह 64-बिट कोड है इसलिए 32-बिट int 0x80 Linux सिस्टम-कॉल ABI का उपयोग करना एक अच्छा विचार नहीं है। कुछ Linux सिस्टम (WSL सहित) में CONFIG_IA32_EMULATION नहीं है और वे उसी तरह दोष देंगे जैसे वे int 0x81 या किसी अन्य सॉफ़्टवेयर व्यवधान के लिए करते हैं। यदि आप 64-बिट कोड में 32-बिट int 0x80 Linux ABI का उपयोग करते हैं तो क्या होगा?

0
Peter Cordes 10 नवम्बर 2019, 12:06