2016-04-11 4 views
5

मैं CPU की घड़ी की गति के बावजूद निष्पादन को लगभग 0.1 सेकंड रोकना चाहता हूं। कोड सीधे बूट डिवाइस से चलाना चाहिए, इसलिए इसे डॉस इंटरप्ट्स का उपयोग नहीं करना चाहिए।बेयर-मेटल 16 बिट x86 असेंबली में कैसे सोएं?

मैं वर्तमान में int 15h का उपयोग कर रहा हूं, लेकिन ऐसा लगता है कि बीआईपी के चैनल 2 के साथ मैं बीप टोन के साथ संघर्ष कर रहा हूं। मैंने चैनल 0 के बारे में सुना, लेकिन मुझे यह सेट करने के बारे में कोई जानकारी नहीं है।

सटीकता यह महत्वपूर्ण नहीं है, हालांकि, इसे एक ही गति पर पुराने और आधुनिक कंप्यूटरों पर चलाना चाहिए। तो सिर्फ लूपिंग निर्देश एक विकल्प नहीं है।

बीप कोड और नींद आवृत्ति को बदलने और स्पीकर को चालू और बंद करने के लिए मैक्रोज़ का एक गुच्छा है। अगर मैं beepoff से पहले नींद कहता हूं तो बीप बंद नहीं होता है।

%macro beepinit 0 
    mov al, 182 
    out 43h, al 
%endmacro 

%macro beepfreq 0 
    out 42h, al 
    mov al, ah 
    out 42h, al 
%endmacro 

%macro beepon 0 
    in al, 61h 
    or al, 00000011b 
    out 61h, al 
%endmacro 

%macro beepoff 0 
    in al, 61h 
    and al, 11111100b 
    out 61h, al 
%endmacro 

और नींद एक:

%macro sleep 2 
    push dx 
    mov ah, 86h 
    mov cx, %1 
    mov dx, %2 
    int 15h 
    pop dx 
%endmacro 

मैं एनएएसएम कोडांतरक उपयोग कर रहा हूँ

यहाँ बीप मैक्रो नहीं है।

यह How can I create a sleep function in 16bit MASM Assembly x86? का डुप्लिकेट नहीं है, क्योंकि यह विंडोज या डॉस के बाहर नंगे धातु असेंबली के लिए है।

+1

मैं ओएस-निर्भर एक से प्रश्नों को अलग करने के लिए "कैसे नंगे-धातु 16-बिट x86 असेंबली में सोना" शीर्षक बनाने का सुझाव दूंगा। शायद इस प्रश्न में संकेत मिलता है कि आपने int 15h का उपयोग करने का प्रयास कैसे किया है, इस सवाल को प्रश्न को व्यापक बनाने में मदद मिलेगी (यह वर्तमान स्वरूप में सीमा रेखा है)। –

+0

@PascalCuoq ठीक है, मैंने इसे थोड़ा संपादित किया। –

+0

संबंधित: http://stackoverflow.com/a/1862232/509868 – anatolyg

उत्तर

3

प्रोग्राम करने योग्य अंतराल टाइमर जाने का तरीका है। यदि आप केवल नए सिस्टम से निपटेंगे, तो एचपीईटी देखें। पीआईटी के लिए कुछ चीजें जानना है। सबसे पहले, इसे सेट अप करने के लिए आपको पोर्ट शून्य टाइमर को कॉन्फ़िगर करने के लिए नियंत्रण/कमांड पोर्ट के रूप में पोर्ट 0x43 का उपयोग करने की आवश्यकता है। बाइट है कि हम भेजना चाहते हैं वहाँ एक सा मैप किया क्षेत्र है:

7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 
+----------------------------------------------+ 
| Channel | RW Mode | Channel Mode | BCD?| 
+----------------------------------------------+ 

चैनल चैनल शून्य चयन करने के लिए साफ हो जाएगा।

आरडब्ल्यू मॉडल 1-एलएसबी, 2-एमएसबी या 3-एलएसबी हो सकता है जिसके बाद एमएसबी हो सकता है। हम दोनों बिट्स (3, 011 के बिट पैटर्न) चाहते हैं क्योंकि हमें 16 बिट वैल्यू (एलएसबी फिर एमएसबी)

चैनल मोड के लिए हम एक स्क्वायर वेव भेजना चाहते हैं। यह 3 (011)

का एक छोटा सा पैटर्न है, हम काउंटर के लिए 16 बिट डिवीजर भेजना चाहते हैं, बीसीडी मूल्य नहीं, इसलिए सबसे कम बिट साफ़ हो गया है।

यह हमें देता है: 000110110 बाइनरी में या 0x36 हेक्स में। अब हम इसे सेट अप:

mov al, 0x36 ; 0x36 from our work above 
out 0x43, al ; Send that byte to the control port 

mov ax, 11931 ; The timer ticks at 1193182. 100hz would be 1193182/11931 
out 0x40, al ; send low byte 
out 0x40, ah ; send high byte 

इस बिंदु आप अगर आप एक बाधा (IRQ 0) करने के लिए प्रतिक्रिया करने के लिए जा रहे हैं या बस घड़ी पढ़ना चाहते हैं यह तय करना होगा पर। मैं आपको ओएसडीव पर this excellent reference पर इंगित करूंगा जिसमें उदाहरण कोड के साथ दोनों पर एक शानदार लेखन है।

+0

समस्या यह है कि ओएसडीव पर उदाहरण कोड 32-बिट असेंबली के लिए बनाया गया है। –

+0

... यह एक समस्या क्यों है? यह 16 बिट या वैकल्पिक रूप से, BIOS इंटरप्ट को पीछे छोड़ने और संरक्षित मोड पर जाने के लिए अनुवाद करना बहुत आसान है। –

+0

उदाहरण के लिए, मैंने जिस कोड को यहां पोस्ट किया है (सभी 16 बिट) आप या तो संक्रमण गणना प्राप्त करने या आईआरक्यू 0 के लिए एक आईएसआर स्थापित करने के लिए समय-समय पर चैनल शून्य पढ़ सकते हैं। 32 और 16 बिट कोड के बीच वास्तव में कुछ भी नहीं बदलता यह पते के आकार को छोड़कर चला जाता है। –

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