หน้าเว็บ

วันอังคารที่ 13 ธันวาคม พ.ศ. 2554

เขียนเพลง ด้วยภาษา Assembly

        อันนี้เป็นเพลงคล้ายๆ กับเพลงริงโทนของโทรศัพท์มือถือครับ  ซึ่งใช้ภาษา Assembly ในการเขียน
ด้วยการทำให้ลำโพง BIOS ดังเป็นจังหวะเพลงตามตัวโน๊ตที่เราได้เขียนลงไป



        งานนี้ผมเคยทำตอนที่เรียนอยู่ปี 2 และปี 3  ครับ  วิชา Assembly และวิชา Interface  อาจารย์ให้นำความรู้จากการที่ได้เรียน Assembly และ Interface มาเขียนเป็นเพลง   จะเขียนเพลงอะไรนั้นก็ตามใจเรา  ซึ่งผมเคยเขียนอยู่ 2 เพลงด้วยกัน  คือเพลง Numb ของ Linkin Park และเพลง Cannon Rock  มันสุดยอดมากเลยครับสองเพลงนี้  ผมชอบมากกกกกกกกก  ก็เลยตัดสินใจเอามาเขียนเป็นเพลง  เริ่มนอกเรื่องแล้ว ฮ่าๆๆๆๆๆ

เรามาดูโค๊ดกันเลยดีกว่าครับ  ต้องบอกก่อนว่า  มันเยอะมากกกกกกก



.MODEL    SMALL  ;จองหน่วยความจำเป็นขนาด SMALL

.DATA  ;กำหนดค่าคงที่ให้กับตัวแปรต่างๆครับ

;ความถี่เสียงต่างๆนี้ผมได้คำนวณไว้เรียบร้อยแล้ว  สามารถนำไปใช้ได้เลยครับ
;ความถี่เสียงของตัวโน๊ต  A
A0 EQU 0A979H
A1 EQU 54BDH
A2 EQU 2A5EH
A3 EQU 152FH
A4 EQU 0A98H
A5 EQU 054CH
A6 EQU 02A6H
A7 EQU 0152H

;ความถี่เสียงของตัวโน๊ต  A#
AC0 EQU 9FF7H
AC1 EQU 4FFBH
AC2 EQU 27EEH
AC3 EQU 13FFH
AC4 EQU 09FFH
AC5 EQU 0500H
AC6 EQU 0280H
AC7 EQU 0140H

;ความถี่เสียงของตัวโน๊ต  B
B0 EQU 96FCH
B1 EQU 4B7EH
B2 EQU 25BFH
B3 EQU 12E0H
B4 EQU 0970H
B5 EQU 04B8H
B6 EQU 02A6H
B7 EQU 012EH

;ความถี่เสียงของตัวโน๊ต  C
C1 EQU 8E83H
C2 EQU 4741H
C3 EQU 23A1H
C4 EQU 11D0H
C5 EQU 08E8H
C6 EQU 0474H
C7 EQU 023AH
C8 EQU 011DH

;ความถี่เสียงของตัวโน๊ต  C#
CC1 EQU 8683H
CC2 EQU 4341H
CC3 EQU 21A1H
CC4 EQU 10D0H
CC5 EQU 0869H
CC6 EQU 0434H
CC7 EQU 021AH

;ความถี่เสียงของตัวโน๊ต  D
D1 EQU 7EE6H
D2 EQU 3F78H
D3 EQU 1FBEH
D4 EQU 0FDFH
D5 EQU 07EFH
D6 EQU 03F8H
D7 EQU 01FCH

;ความถี่เสียงของตัวโน๊ต  D#
DC1 EQU 77D6H
DC2 EQU 3BEBH
DC3 EQU 1DF6H
DC4 EQU 0EFBH
DC5 EQU 077DH
DC6 EQU 03BFH
DC7 EQU 01DFH

;ความถี่เสียงของตัวโน๊ต  E
E1 EQU 711DH
E2 EQU 388EH
E3 EQU 1C47H
E4 EQU 0E24H
E5 EQU 0712H
E6 EQU 0389H
E7 EQU 01C4H

;ความถี่เสียงของตัวโน๊ต  F
F1 EQU 6AC2H
F2 EQU 3562H
F3 EQU 1AB1H
F4 EQU 0D58H
F5 EQU 06ACH
F6 EQU 0356H
F7 EQU 01ABH

;ความถี่เสียงของตัวโน๊ต  F#
FC1 EQU 64C5H
FC2 EQU 3263H
FC3 EQU 1931H
FC4 EQU 0C99H
FC5 EQU 064CH
FC6 EQU 0326H
FC7 EQU 0193H

;ความถี่เสียงของตัวโน๊ต  G
G1 EQU 5F1DH
G2 EQU 2F8FH
G3 EQU 17C7H
G4 EQU 0BE4H
G5 EQU 05F2H
G6 EQU 02F9H
G7 EQU 017CH

;ความถี่เสียงของตัวโน๊ต  G#
GC1 EQU 59C7H
GC2 EQU 2CE3H
GC3 EQU 1672H
GC4 EQU 0B39H
GC5 EQU 053CH
GC6 EQU 02CEH
GC7 EQU 0167H

;คอนโทรลต่างๆครับ  เช่นการกำหนดพอร์ต  การรับ การส่งข้อมูล  พอร์ตของลำโพง  และอื่นๆ
CONTROL_WORD EQU 10110110B ;0B6H
COUNTER2 EQU 42H
CONTROL_REGISTER_PORT EQU 43H
;------------------------------------------END DECLARATION NOTE----------------------------------------------------

;กำหนดค่าให้   SOLO  เป็นจุดอ้างอิงเริ่มต้นของตัวโน๊ต
SOLO        
            DW 0H 
            DB 5,10
           
            ;-------------9(T==90)
            DW FC6 ;1   ;บอกว่าให้เป็นเสียง F#6
            DB 35,1  ;มีความยาวเสียงนาน 35 หน่วย  ปิดเสียง(เงียบ) 1 หน่วย
           
            DW E6 ;2  ;บอกว่าให้เป็นเสียง E6
            DB 35,1  ;มีความยาวเสียงนาน 35 หน่วย  ปิดเสียง(เงียบ) 1 หน่วย
            ;-------------10
            DW D6 ;3  ;บอกว่าให้เป็นเสียง D6
            DB 35,1  ;มีความยาวเสียงนาน 35 หน่วย  ปิดเสียง(เงียบ) 1 หน่วย
           
            DW CC6 ;4
            DB 35,1
            ;-------------11
            ....
            ....
            ....
            ;ใส่ตัวโน๊ตไปเรื่อยๆครับ  จนกว่าจะจบเพลง

;----------------------------------------------------MAIN PROGRAM-----------------------------------------------------             
         .CODE  ;เป็นส่วนของการเขียนโค๊ดการทำงานของ assembly จริงๆครับ   เขียนแยกเป็นฟังก์ชันไว้
MAIN     PROC    NEAR
                MOV    SI,0
                MOV    AX,@DATA
                MOV    DS,AX
                MOV    AL,CONTROL_WORD
                OUT    CONTROL_REGISTER_PORT,AL
                MOV    BX,OFFSET SOLO  ;อ่านค่าตัวโน๊ตจาก SOLO  มาใช้
    CHANGE:        MOV    AX,[BX+SI]
                CALL    SET_TIMER2  ;เซตเวลาว่าจะให้ลำโพงเปิดหรือปิดนานแค่ไหน  เช่นตามค่า  DB 35,1
                CALL    SPK_ON  ;เปิดลำโพง
                INC    SI
                MOV    CL,[BX+SI]
    START_DELAY_OFF: CALL    DELAY
                     LOOP    START_DELAY_OFF
                     INC    SI
                     MOV    AX,[BX+SI]
                     CMP    AX,0
                     JZ    OUT_LOOP
                     JMP    CHANGE
    OUT_LOOP:    MOV    AH,4CH
                INT 21H
MAIN    ENDP
;---------------------------------------------------SET TIMER2--------------------------------------------------------
SET_TIMER2     PROC    NEAR
         OUT    COUNTER2,AL
         MOV    AL,AH
         OUT    COUNTER2,AL
    RET
SET_TIMER2     ENDP
;---------------------------------------------------SPEEKER ON--------------------------------------------------------
SPK_ON  PROC    NEAR
            PUSH    AX
                     IN    AL,61H
                     MOV    AH,AL
                     OR    AL,3
                     OUT    61H,AL
                     ADD    SI,2
                     MOV    CL,[BX+SI]
    START_DELAY_ON:     CALL    DELAY
                     LOOP    START_DELAY_ON
                     MOV    AL,AH
                     OUT    61H,AL
            POP    AX
    RET
SPK_ON  ENDP
;-----------------------------------------------------DELAY-----------------------------------------------------------
DELAY   PROC    NEAR
             PUSH    AX
             PUSH    CX
                 MOV    CX,7900H ;DELAY VALUE 
                 ;ตรงนี้เป็นความถี่ที่จะนำไปคำนวณเรื่องของดีเลย์เสียงครับ  ที่ผมเซตไว้สำหรับเครื่องของผมเท่านั้น   ซึ่งแต่ละเครื่องจะไม่เหมือนกัน  ถ้าเล่นเพลงไปแล้วจังหวะเพลงมันช้า  เราก็ปรับให้มันมีค่าน้อยลงครับ  แต่ถ้าจังหวะเพลงมันเร็วไป  เราก็เพิ่มดีเลย์ให้มัน  ก็ลองๆเซตจนกว่ามันจะพอดีครับ    แต่ความจริงแล้วมันมีสูตรคำนวณอยู่  โดยเอาความถี่ CPU ของเครื่องเรามาคิด  แต่ผมจำวิธีคิดมันไม่ได้แล้วแหล่ะครับ ฮ่าๆๆๆๆ

        WAIT1:     IN    AL,61H
                 AND    AL,10H
                 CMP    AL,AH
                 JE    WAIT1
                 MOV    AH,AL
                 LOOP    WAIT1
             POP    CX
             POP    AX
    RET
DELAY     ENDP
        END    MAIN


เมื่อเขียนโค๊ดเสร็จ  เราก็ save ไว้เป็น .asm

        ถ้าถามว่าผมรู้ได้ยังไงว่าเพลงแต่ละเพลงมีตัวโน๊ตอะไรบ้าง  ทั้งๆที่ความจริงแล้ว  ผมเล่นดนตรีไม่เป็นเลยซักนิด  ฮ่าๆๆๆ    ผมก็ขอตอบอย่างภูมิใจไปเลยครับว่า  ผมใช้โปรแกรมแกะเพลงเอา ฮ่าๆๆๆ   แล้วก็เอาตัวโน๊ตที่ได้มาเขียนลงไปครับ  ผมใช้โปรแกรม  Guitar Pro  ครับ  ช่วงนั้นเป็น version 5   ซึ่งเราเองก็ต้องไปหาไฟล์เพลงที่เป็นของ Guitar Pro มา  แล้วก็เอามาแกะตัวโน๊ตเอาครับ  ผมเองก็นั่งแกะ Cannon Rock นานเป็นอาทิตย์อยู่เหมือนกัน  เพราะเพลงมันยาวประมาณ 10 นาที  ถือว่าบ้าบิ่นพอสมควรที่เลือกเพลงนี้   ทำไงได้  ก็คนมันชอบนี่นา  ทำอะไรก็ขอทำให้มันสุดๆ ไปเลยแล้วกันครับ  ^____^



นอกเรื่องนานแล้ว  มาเข้าเรื่องกันต่อดีกว่าครับ

        เครื่องผมเป็น Windows 7 ครับ  ก็เลยต้องมีโปรแกรมเสริมที่ใช้สำหรับ Run โปรแกรม Assembly  เพราะว่า Windows 7  Run  Assembly ไม่ได้    โปรแกรมเสริมตัวนั้นคือ  DOSBox  ครับ  
สามารถดาวน์โหลดฟรีได้ที่  http://www.dosbox.com/download.php?main=1   


        ติดตั้งให้เสร็จก่อนครับ  ติดตั้งง่ายๆ  แค่ใช้ Next Technology ที่เราได้ร่ำเรียนมาอย่างเดียว ฮ่าๆๆๆๆ
แล้วก็ดาวน์โหลดอีกตัวนึงมา   คือโปรแกรม TASM  ใช้สำหรับ Compile แล้วก็ Building Code  
สามารถดาวน์โหลดได้ที่   http://www.softpedia.com/progDownload/TASM-Editor-Download-128562.html
ระหว่างที่เรากดดาวน์โหลด TASM ให้รอนิดหน่อยน่ะครับ  มันอาจจะขึ้นลิงค์ใหลดช้าหน่อย  แต่ได้ชัวร์ๆ ครับ


        ตอนโหลดมาจะเป็นไฟล์ .zip ก็ให้แตกไฟล์ก่อน  จะแตกไฟล์ไว้ที่ไหนก็ได้  ซึ่งผมขอเอาไว้ที่ไดรฟ์ C:\ น่ะครับ


นี่คือหน้าตาของ TASM 


        จากนั้นให้เรานำไฟล์เพลง .asm  ที่เราได้เขียนไว้  ไปไว้ใน folder TASM  ครับ
          แล้วก็  Run  DOSBox ขึ้นมา นี่คือหน้าตาของ DOSBox ครับ


        จากนั้นให้  Mount  DOSBox ไปที่ๆ เก็บ TASM ไว้  ดังนี้

Z:\>mount c c:\tasm
Z:\>c:
C:\>dir


        แล้วก็  Compile ไฟล์เพลง  
        จะต้องไม่มี  Error  เกิดขึ้น  ถ้าหากมี  ให้แก้ให้หมดก่อนน่ะครับ  ไม่งั้นมัน Run ไม่ได้ ^_____^

C:\>tasm cannon.asm

 
แล้วก็  Run  เพลงดังนี้

C:\>tlink cannon        ตรงนี้ต้องไม่มี .asm เท่านั้น ****
C:\>cannon.exe 



        เพียงแค่นี้เราก็จะมีเพียงริงโทน Assembly เป็นของเราเองแล้ว  เท่โคตร ฮ่าๆๆๆๆ  มันจะเป็นเสียงเพลงตี๊ด ติ๊ด ติ๊ด  ออกมาเหมือนเสียงริงโทนโทรศัพท์สมัยก่อนเลยครับ
        หากเพลงมันช้าไปเราสามารถเพิ่มความเร็วได้โดยการกด Ctrl + F12  ซึ่งจะเป็นการเพิ่ม CPU Speed ของเครื่อง  ถ้าตกการลดก็ให้กด Ctrl + F11  ครับ  ถ้าจะพูดอีกอย่างก็คือการเพิ่มลดดีเลย์เสียงนั่นเอง

สังเกตุจากตรงนี้  


ถ้าเป็น Windows XP  ไม่ต้องลง DOSBox ครับ  เพราะมัน Run Assembly ได้  ลงแค่ TASM ก็พอแล้ว  การ Complie หรือ Run Code  จะมีขั้นตอนการทำเหมือนกันทุกอย่างครับ




        อันนี้เป็นเพลงที่ผมเขียนเองครับ  ซึ่งเป็นเพลงที่ผมโปรดทั้ง 2 เพลงเลย ^^   จังหวะอาจจะดูเร็วไปนิดครับ  เพราะว่าผมเพิ่ม CPU Clock Speed  มากไปนิดนึงครับ  แต่จังหวะก็โอเคอยู่ครับ
        เป็นเสียงของลำโพง BIOS  น่ะครับมันก็เลยดัง ติ๊ด ติ๊ด ดิ๊ด  ซึ่งเสียงแต่ละเสียงจะขึ้นอยู่กับความถี่เสียงของตัวโน๊ตแต่ละตัว  

เพลง Cannon Rock  ด้วย Assembly  เขียนตอนปี 3  


 

เพลง Numb Linkin Park  ด้วย Assembly  เขียนตอนปี 2




 
เป็นยังไงกันบ้างครับ  หวังว่าคงได้อะไรสนุกๆ ไปเล่นกันน่ะ ^^ 


2 ความคิดเห็น:

  1. โค้ดมันเออเร่อตรง .MODEL SMALL อ่ะคะ

    ตอบลบ
  2. ทำไมเสียงมันไม่เบรคอ่าคร๊าฟ ต้องแก้อย่างไงหรอคร๊าฟ

    ตอบลบ