วันพฤหัสบดีที่ 13 สิงหาคม พ.ศ. 2552

โปรแกรมภาษาแอสเซมบลี

การโปรแกรมภาษาแอสเซมบลีนอกจากต้องศึกษาถึงคำสั่งในบทแรกเราได้ศึกษามาแล้วว่าเฉพาะตัวเลขฐานสองเท่านั้นที่ใช้ได้กับการโปรแกรมภาษาเครื่อง แต่เมื่อใช้ภาษาแอสเซมบลี ผู้เขียนโปรแกรมสามารถใช้ระบบเลขฐานอื่นเพื่อความสะดวกในการเขียนโปรแกรมยิ่งขึ้น เช่น ใช้เลขฐานสิบ หรือเลขฐานสิบหก เป็นต้น นอกไปจากนี้ภาษาแอสเซมบลียังเอื้ออำอำนวยต่อกำหนดแบบข้อมูลเบื้องต้นสำหรับใช้ในตัวโปรแกรม ด้วยเหตุนี้ผู้เขียนโปรแกรมจึงจำเป็นต้องทำความเข้าใจถึงระบบเลขฐานและวิธีการ แทนข้อมูลตามแบบที่ภาษาแอสเซมบลีกำหนดซึ่งประกอบไปด้วยเนื้อหาหลักดังนี้
ระบบเลขฐาน
การแทนเลขบวกและลบ
ค่าบูลีน
เลขรหัสไบนารีฐานสิบ
เลขทศนิยม
อักขระและสายอักขระ
การใช้รีจิสเตอร์
คำสั่งในภาษาแอสเซมบลีแทบทุกคำสั่งจะใช้รีจิสเตอร์เป็นตัวเก็บข้อมูลที่ต้องประมวลผล ในที่นี้เราจะศึกษาถึงการใช้งานรีจิสเตอร์เบื้องต้น 4 ตัว ได้แก่ AX, BX, CX และ DX ตัวอย่างคำสั่งคำนวณเบื้องต้นต่อไปนี้เป็นคำสั่งกำหนดให้รีจิสเตอร์ AX เท่ากับ 5 และบวกค่าเพิ่มอีก 1 ให้ AX เท่ากับ 6

mov ax,5
add ax,1

คำสั่ง MOV สามารถใช้เคลื่อนย้ายข้อมูลระหว่างรีจิสเตอร์ด้วยกันได้ ตัวอย่างเช่น หากให้ AX มีค่าเท่ากับ 6 คำสั่งต่อไปนี้จะทำให้รีจิสเตอร์ BX, CX และ DX มีค่าเท่ากับ 6 ด้วยเช่นกัน

mov ax,bx
mov cx,bx
mov dx,ax

8086 มีคำสั่ง INC ใช้เพิ่มค่ารีจิสเตอร์ครั้งละหนึ่ง แทนการบวกค่าด้วยคำสั่ง ADD คำสั่งต่อไปนี้จะเพิ่มค่าให้รีจิสเตอร์ DX ขึ้นอีกหนึ่ง

inc dx

8086 ยังมีคำสั่งคำนวณอื่นเกี่ยวกับการลบและการคูณ เช่น ชุดคำสั่งต่อไปนี้

mov ax,6
mov bx,5
sub ax,2
mul bx

คำสั่งข้างต้นทำหน้าที่คำนวณนิพจน์ (6-2)*5 คำสั่ง MUL จะนำค่า AX คูณกับ BX ได้ 14H ผลลัพธ์การคูณเลข 16 บิต จะได้เลขขนาด 32 บิตเสมอ ค่าที่ได้จากคำสั่งคูณข้างต้นคือ 00000014Hตัวเลขขนาด 32 บิตนี้จะถูกแบ่งเก็บไว้ในรีจิสเตอร์ DX และ AX อย่างอัตโนมัติ โดย DX เก็บค่า 0000H และ AX เก็บค่า 0014H แต่ละคำสั่งจะทำให้รีจิสเตอร์แต่ละตัวเปลี่ยนแปลงไปดังนี้



รีจิสเตอร์

AX

BX

CX

DX
ค่าเริ่มต้น
?
?
?
?
mov ax,6
6
?
?
?
mov bx,5
6
5
?
?
sub ax,2
4
5
?
?
mul bx
14H
5
?
0
การใช้รีจิสเตอร์ 8 บิต และ 16 บิต
การเคลื่อนย้ายข้อมูลระหว่างรีจิสเตอร์จะต้องเกิดขึ้นกับรีจิสเตอร์ที่มีขนาดเท่ากันเสมอ ตัวอย่างเช่นการเคลื่อนย้ายข้อมูลแบบ 8 บิตและ 16 บิต ดังตัวอย่าง

mov al,bl
mov dh,cl
mov ax,bx
mov cx,dx

แต่คำสั่งต่อไปนี้ไม่อนุญาตให้มีได้ในโปรแกรม

mov al,dx
mov cx,bh

รีจิสเตอร์ย่อย 8 บิต ถือว่าเป็นส่วนหนึ่งของรีจิสเตอร์ 16 บิตด้วย การเปลี่ยนแปลงค่าในรีจิสเตอร์ 8 บิตย่อมกระทบถึงรีจิสเตอร์ 16 บิต โดยตรง ตัวอย่างเช่นคำสั่ง

mov ch,32h
mov cx,152eh
inc ch

จะทำให้ค่าในรีสเตอร์ CH เท่ากับ 16H และ CX เท่ากับ 162EH ตามขั้นตอนต่อไปนี้




CH
CL
CX

??
??
????
mov ch,32h
32h
??
32??
mov cx,152eh
15h
2eh
152eh
inc ch
16h
2eh
162eh

คำสั่งเกี่ยวกับรีจิสเตอร์ 8 บิต อาจทำให้เกิดความคลุมเครือระหว่างชื่อรีจิสเตอร์และตัวเลขฐานสิบหก ดังเช่น

mov cl,ah

อาจหมายถึงการนำค่าจากรีจิสเตอร์ AH ไปไว้ที่ CL หรือ อาจหมายถึงค่า 0AH ไปไว้ที่ CL
เพื่อป้องกันความสับสนนี้ แอสเซมเบลอร์กำหนดให้ตัวเลขฐานสิบหกที่ขึ้นต้นด้วย A ถึง F จะต้องมีเลข 0 นำหน้าเสมอ เช่นค่า AH จะต้องเขียนแทนด้วย 0AH หรือค่า E12DH ก็ต้องเขียนเป็น0E12DH
การอ้างอิงหน่วยความจำ
คำสั่งใน 80x86 มีรูปแบบอ้างอิงกับหน่วยความจำได้หลายแบบ และอาจเป็นการอ้างอิงกับข้อมูล 8 บิต หรือ 16 บิต ก็ได้ตัวอย่างเช่นคำสั่งเคลื่อนย้ายข้อมูล

mov bl, [20h]

เป็นคำสั่งนำค่าจากหน่วยความจำตำแหน่ง 20h มาไว้ในรีจิสเตอร์ bl และคำสั่ง

mov ax, [20h]

เป็นคำสั่งนำค่าจากหน่วยความจำตำแหน่ง 20h และ 21h มาไว้ในรีจิสเตอร์ ax เครื่องหมายวงเล็บเหลี่ยมหมายถึงการนำค่าจากหน่วยความจำตำแหน่งที่กำหนด ความหมายของ [20h] จึงเท่ากับค่าในแอดเดรส 20h สำหรับการเคลื่อนย้ายข้อมูลจากรีจิสเตอร์ไปสู่หน่วยความจำจะสลับตำแหน่งของโอเปอร์แรนด์ดังเช่นคำสั่ง

mov [20h],ax

หมายถึงการนำค่าจากรีจิสเตอร์ ax ไปเก็บไว้ที่หน่วยความจำตำแหน่ง 20h หากรีจิสเตอร์ ax มีค่า 2e3fh คำสั่งดังกล่าวจะทำให้ตำแหน่ง 20h มีค่า 3fh และตำแหน่ง 21h มีค่าเป็น 2eh ทั้งนี้เป็นไปตามหลักของตำแหน่งนัยสำคัญมากสุดและน้อยที่สุดดังรูปที่ 4.1
จากหลักการเรื่องเซกเมนต์ของซีพียูตระกูล 8086 หน่วยความจำที่อ้างอิงอยู่ในรูปของวงเล็บก็คือค่าออฟเซ็ตของเซกเมนต์ข้อมูล อย่างเช่นคำสั่ง

mov al,[100h]

ซึ่งเป็นการอ้างอิงถึงออฟเซตที่ 100h ของเซกเมนต์ข้อมูลที่ชี้อยู่ด้วยรีจิสเตอร์ ds ค่าแอดเดรสสัมบูรณ์ขนาด 20 บิต ที่ซีพียูติดต่อกับหน่วยความจำ จะหาได้จากหลักการที่ได้กล่าวมาไว้ในบทที่แล้ว



mov ax,[20h]




ah
al


ออฟเซ็ต
ax
3fh
2eh






2eh
20h




3fh
21h







mov [20h],ax




ah
al


ออฟเซ็ต
ax
3fh
2eh






2eh
20h




3fh
21h







รูปที่ 4.1 การเคลื่อนย้ายข้อมูลระหว่างรีจิสเตอร์กับหน่วยความจำแบบ 16 บิต

คุณสมบัติพิเศษของรีจิสเตอร์ BX
รีจิสเตอร์ bx เป็นรีจิสเตอร์ตัวหนึ่งที่มีคุณสมบัติพิเศษในการใช้อ้างอิงข้อมูลกับหน่วยความจำ เนื่องจากเราสามารถใช้ค่าของรีจิสเตอร์เป็นตัวชี้ไปยังหน่วยความจำที่ต้องการติดต่อด้วยแทนการกำหนดด้วยตัวเลขหน่วยความจำตรงๆ ดังเช่น

mov al,[bx]

หมายถึงให้นำค่าจากหน่วยความจำที่ตำแหน่งซึ่งกำนหดด้วย bx มาไว้ใน al หรือเรียกว่า นำค่าจากตำแหน่งที่ชี้ด้วย bx มาไว้ใน al
ในกลุ่มของรีจิสเตอร์เอนกประสงค์ 4 ตัว คือ ax, bx, cx และ dx นั้น มีเพียงเฉพาะรีจิสเตอร์ bx เพียงตัวเดียวเท่านั้นที่ใช้การอ้างอิงนี้ได้ การใช้รีจิสเตอร์อื่นเช่น cx ด้วยคำสั่ง

mov al,[cx]

ถือว่าผิดรูปแบบ หากแอสเซมเบลอร์ตรวจพบก็จะแสดงข้อผิดพลาดออกมา
การใช้รีจิสเตอร์ bx ตามรูปแบบข้างต้นมีประโยชน์อย่างยิ่งต่อการเขียนโปรแกรมที่ต้องอ้างอิงกับกลุ่มหน่วยความจำอย่างต่อเนื่องทีละไบต์หรือทีละเวิร์ด โปรแกรมประเภทนี้มักเป็นโปรแกรมที่ทำงานเป็นวงรอบและใช้คำสั่งกระโดดแบบตัดสินใจอย่างเช่นคำสั่ง jnz (กระโดดเมื่อผลลัพธ์คำนวณ ล่าสุดไม่เป็นศูนย์) ตามโปรแกรมตัวอย่างต่อไปนี้

mov bx,500h
mov cl,50h
next_inc: mov al,[bx]
inc al
mov [bx],al
dec cl
jnz next_inc

เมื่อเสร็จสิ้นการทำงานของโปรแกรมข้างต้น ค่าในตำแหน่ง 500h ถึง 54fh จะเพิ่มค่าตำแหน่งละหนึ่ง
การจัดสรรเนื้อที่หน่วยความจำ
ผู้เขียนโปรแกรมภาษาแอสเซมบลี ต้องจัดสรรเนื้อที่หน่วยความจำสำหรับใช้เป็นที่เก็บข้อมูลสำหรับใช้เป็นตัวแปรหรือค่าคงตัว มาโครแอสเซมเบลอร์มีคำสั่งเทียมสำหรับใช้จัดสรรเนื้อที่หน่วยความจำรวม 5 คำสั่งคือ

db (define byte)
dw (define word)
dd (define doubleword)
dq (define quadword)
dt (define tenbytes)

แต่ละคำสั่งจะกำหนดขนาดหน่วยความจำแตกต่างกันไปเรียงจาก 1, 2, 4, 8 และ 10 ไบต์ ตามลำดับ ตามตัวอย่าง

db 2ah ; จัดสรรเนื้อที่ 1 ไบต์ ให้เก็บค่า 2ah
db ? ; จัดสรรเนื้อที่ 1 ไบต์ โดยไม่กำหนดค่า
db 's' ; จัดสรรเนื้อที่ 1 ไบต์ เก็บรหัสแอสกีของ 's'
dw 0a3ch ; จัดสรรเนื้อที่ 2 ไบต์ เก็บค่า 0a3ch
dd 1a2b3c4dh ; จัดสรรเนื้อที่ 4 ไบต์ เก็บค่า 1a2b3c4dh
dq 05h ; จัดสรรเนื้อที่ 8 ไบต์ เก็บค่า 05h
dt ? ; จัดสรรเนื้อที่ 10 ไบต์ โดยไม่กำหนดค่า

ผู้เขียนโปรแกรมสามารถใช้คำสั่งเทียมกำหนดข้อมูลในหน่วยความจำแบบต่อเนื่องกันไปโดยใช้เครื่องหมายจุลภาคคั่นระหว่างข้อมูลแต่ละตัวดังเช่น

db 35h, 7ah, 'a', 'z'
dw 0135h, 0a1a1h

คำสั่งข้างให้ผลการจัดสรรเนื้อที่เช่นเดียวกับการแยกใช้คำสั่งเทียมหนึ่งคำสั่งต่อหนึ่งบรรทัดดังต่อไปนี้

db 35h
db 7ah
db 'a'
db 'z'
dw 0135h
dw 0a1a1h

การจัดสรรเนื้อที่หน่วยความจำให้กับสายอักขระ นิยมใช้เครื่องหมายคำพูดกำกับส่วนต้นและส่วนท้ายสายอักขระดังเช่น

db 'Assembly language'
คำสั่งเทียม dup
แอสเซมเบลอร์ยังมีคำสั่งเทียม dup (duplicate) สำหรับใช้ร่วมกับคำสั่ง db,dw, ฯลฯ เพื่อจัดสรรข้อมูลเป็นกลุ่มซ้ำค่ากันเช่น
db 8h dup (10h) ; จัดสรรเนื้อที่ 8 ไบต์ ให้ทุกไบต์มีค่า 10H
db 20h dup (?) ; จัดสรรเนื้อที่ 32 ไบต์ โดยไม่กำหนดค่า
db 0ffh dup ('a') ; จัดสรรเนื้อที่ 256 ไบต์ ให้ทุกไบต์มีค่า 'a'
dw 20h dup (0) ; จัดสรรเนื้อที่ 32 เวิร์ด ให้ทุกเวิร์ดมีค่าเป็นศูนย์

ตัวแปร
ภาษาแอสเซมบลีมีวิธีกำหนดตัวแปรด้วยคำสั่งเทียมจัดสรรหน่วยความจำ และใช้ชื่อเลเบลเป็นชื่อประจำตัวตัวแปรนั้น ตัวอย่างเช่นการกำหนดตัวแปรดังต่อไปนี้

factor dw 0050h
accept db 'y'
reject db 'n'

เมื่อต้องการใช้ตัวแปรใดก็อ้างด้วยชื่อเลเบลใด เช่นคำสั่งอ่านค่าในตัวแปร factor มาเก็บไว้ในรีจิสเตอร์ 16 บิต ตามขนาดของตัวแปรให้ใช้คำสั่ง

mov ax,factor

หรือเปลี่ยนค่าตัวแปร factor ไปเป็น 3100h ด้วยคำสั่ง

mov bx,3100h
mov factor,bx

การอ้างอิงกับตัวแปร accept และ reject ซึ่งเก็บอักขระ 8 บิต ก็ให้ใช้รีจิสเตอร์ขนาด8 บิต ด้วย ดังเช่นคำสั่ง

mov al,accept
mov bl,reject

แอสเซมเบลอร์จะทำหน้าที่คำนวณค่าออฟเซ็ตประจำตัวแปรนั้นแล้วแปลงชื่อตัวแปรไปเป็นตัวเลขเมื่อเราสั่งแปลโปรแกรม ตัวอย่างเช่นหากว่าตัวแปร factor อยู่ที่ตำแหน่ง 3000h:5100h แอสเซมเบลอร์จะแปลงคำสั่ง

mov ax,factor

ไปเป็น

mov ax,[5100h]

ออฟเซ็ต
แอสเซมเบลอร์มีคำสั่งเทียม offset สำหรับใช้อ้างอิงถึงค่าออฟเซ็ตของตัวแปรในโปรแกรม ขอให้พิจารณาถึงตัวแปร factor ที่ได้อธิบายผ่านมา หากต้องการค่าออฟเซ็ตของ factor ให้ใช้ คำสั่งเทียม offset นำหน้าชื่อตัวแปรดังนี้

mov ax, offset factor

แอสเซมเบลอร์จะแปลงคำสั่งข้างต้นเป็น

mov ax, 5100h

หรือนำค่าออฟเซ็ตของ factor มาใช้
การกำหนดเซกเมนต์
ในบทที่ 3 เราได้ศึกษาถึงหลักการของเซกเมนต์ในซีพียู 8086 มาแล้ว ในหัวข้อนี้จะได้กล่าวถึงวิธีการกำหนดเซกเมนต์ขึ้นใช้ในตัวโปรแกรม
ผู้เขียนโปรแกรมภาษาแอสเซมบลีควรจัดให้มีเซกเมนต์ในโปรแกรม 3 เซกเมนต์เสมอได้แก่ เซก เมนต์คำสั่ง เซกเมนต์ข้อมูล และ เซกเมนต์สแต็ก
เซกเมนต์แสต็ก
เซกเมนต์ที่ทำหน้าที่เป็นสแต็ก ผู้เขียนโปรแกรมจะต้องบ่งบอกอย่างเฉพาะเจาะจงให้แอสเซม เบลอร์ทราบว่าเป็นเซกเมนต์สแต็ก โดยใช้คำสั่งเทียม .stack ดังตัวอย่างต่อไปนี้

.stack 100h dup(?)
การกำหนดรีจิสเตอร์ DS
โปรแกรมทุกโปรแกรมที่มีเซกเมนต์แยกต่างหากออกจากเซกเมนต์คำสั่ง ผู้เขียนโปรแกรมจะต้องเขียนคำสั่งกำหนดค่ารีจิสเตอร์ ds ให้ชี้ไปที่ต้นเซกเมนต์ข้อมูลก่อนคำสั่งอื่นใด การกำหนดค่าให้กับรีจิส เตอร์เซกเมนต์ใดๆ จะต้องอาศัยรีจิสเตอร์ 16 บิต ตัวอื่นเป็นตัวช่วยเสมอ เนื่องจาก 8086 ไม่มีคำสั่งกำหนดค่าตัวเลขโดยตรงให้กับรีจิสเตอร์เซกเมนต์ ในกรณีเช่นนี้เราอาจเลือกรีจิสเตอร์ ax และใช้คำสั่งดังต่อไปนี้

mov ax,@data
mov ds,ax
คำสั่งจบโปรแกรม
แอสเซมเบลอร์จะทำหน้าที่แปลโปรแกรมจนกว่าจะพบคำสั่งเทียม end ผู้เขียนโปรแกรมจะต้องบอกให้แอสเซมเบลอร์ทราบว่าคำสั่งแรกสุดที่โปรแกรมจะต้องทำงานอยู่ที่ตำแหน่งใด โดยการใส่เลเบลประจำคำสั่งนั้นตามหลังคำสั่งเทียม end
เนื่องจากเราเขียนโปรแกรมโดยแยกเซกเมนต์ขอมูลออกจากเซกเมนต์คำสั่ง และต้องกำหนดค่ารีจิสเตอร์ ds เป็นอันดับแรก เลเบลประจำคำสั่งแรกจึงอยู่ที่คำสั่ง mov ax,@data ขอให้ย้อนกลับไปพิจารณาเลเบล start จากตัวอย่างโปรแกรมใบบทที่ 1 ซึ่งตัดตอนมาดังนี้

:
:
.code
start: mov ax,@data
mov ds,ax
:
:

end start


ในการเขียนโปรแกรมที่มีโมดูลเดียวไม่จำเป็นต้องใส่เลเบลประจำคำสั่งแรกต่อท้าย end แต่ในการพัฒนาโปรแกรมขนาดใหญ่และต้องจัดแบ่งโปรแกรมออกเป็นโมดูลย่อยหลาย ๆ โมดูล (มีแฟ้ม .asm หลาย ๆ แฟ้ม) แอสเซมเบลอร์ย่อมไม่ทราบว่าโมดูลใดเป็นโมดูลหลักที่บรรจุคำสั่งเริ่มต้นทำงาน นอกเสียจากว่าผู้เขียนโปรแกรมจะบ่งบอกด้วยการใช้เลเบลต่อท้ายคำสั่ง end ตามวิธีข้างต้น
การจัดลำดับเซกเมนต์
มาโครแอสเซมเบลอร์ masm ให้อิสระต่อผู้เขียนโปรแกรมในการจัดวางลำดับเซกเมนต์ และแอสเซมเบลอร์ปรับรีจิสเตอร์ ip ให้ชี้ไปที่เลเบลตามที่กำหนดหลังคำสั่งเทียม end ตัวอย่างการจัดลำดับเซกเมนต์ในหนังสือเล่มนี้ใช้ลำดับของเซกเมนต์โดยขึ้นต้นด้วยเซกเมนต์สแต็ก, เซกเมนต์ข้อมูล และปิดท้ายด้วยเซกเมนต์คำสั่งดังรูปที่ 4.2
รูปที่ 4.2 นี้สามารถใช้เป็นต้นแบบสำหรับเขียนโปรแกรมภาษาแอสเซมบลีเบื้องต้นได้ต่อไป เพื่อประหยัดเวลาการสร้างโปรแกรม

;--------------------------------------
; upcase.asm
; read string from keyboard and change
; to upper case (undetect errors)
;--------------------------------------
;
.modell small
;
;reserved space for satck
.stack 100h
.data
;define data here

.code

; init data segment
start: mov ax,@data
mov ds,ax

; start of code

; return to dos with errorlevel 0
mov ax,4c00h
int 21h

end start

รูปที่ 4.2 โปรแกรมต้นแบบ แสดงการจัดวางเซกเมนต์

ดอสฟังก์ชัน
เอ็มเอสดอสมีฟังก์ชันบริการงานหลายอย่างที่เกี่ยวข้องกับอุปกรณ์อินพุตเอาต์พุตของไมโครคอมพิวเตอร์ ตัวอย่างฟังก์ชันของดอสได้แก่ฟังก์ชันการอ่านปุ่มกดแป้นพิมพ์ ฟังก์ชันแสดงอักขระบนจอภาพ และฟังก์ชันอ่านหรือเขียนดิสค์เป็นต้น ฟังก์ชันเหล่านี้ช่วยลดงานของผู้เขียนโปรแกรมได้มาก เนื่องจากผู้เขียนโปรแกรมเพียงแต่ศึกษาวิธีการเรียกใช้ฟังก์ชันโดยไม่ต้องคำนึงถึงรายละเอียดการทำงานภายในซึ่งมักจะมีการเชื่อมต่อไปยังฮาร์ดแวร์ของเครื่อง การเรียกใช้ฟังก์ชันของดอสใช้คำสั่ง int (interrupt) ซึ่งเป็นคำสั่งที่ทำให้เกิดการกระโดดไปยังทำงานในบริเวณโปรแกรมที่เป็นส่วนของเอ็มเอสดอส
ซีพียู 8086 ได้รับการออกแบบให้มีอินเตอร์รัพต์แตกต่างกันถึง 256 แบบ แต่ละแบบกำหนดด้วยหมายเลข 00h ถึง ffh เอ็มเอสดอสจะใช้หมายเลข 21h เป็นอินเทอร์รัพต์ประจำตัว และภายในอินเทอร์รัพต์ 21h ของดอสจะบรรจุฟังก์ชันย่อย ๆ มากมายดังที่ยกตัวอย่างไว้ข้างต้น
แต่ละฟังก์ชันของอินเทอร์รัพต์ 21h จะมีหมายเลขประจำตัวเพื่อกำหนดการเรียกใช้ ผู้เขียนโปรแกรมจะต้องใส่หมายเลขประจำฟังก์ชันที่ต้องการไว้ในรีจิสเตอร์ ax ก่อนการใช้ คำสั่ง int 21h ตารางที่ 4.1 แสดงถึงฟังก์ชันสำคัญจำนวนหนึ่งของดอส
ในกลุ่มฟังก์ชันตามตารางที่ 4.1 ฟังก์ชันที่ใช้งานเป็นประจำได้แก่ฟังก์ชัน 1 (อ่านแป้นพิมพ์) ฟังก์ชัน 2 (แสดงอักขระบนจอภาพ) ฟังก์ชัน 9 (แสดงสายอักขระบนจอภาพ) และฟังก์ชัน 0AH (อ่านสายอักขระจากแป้นพิมพ์) หัวข้อถัดไปจะอธิบายถึงการใช้ฟังก์ชันเหล่านี้โดยละเอียด


ตารางที่ 4.1 ตัวอย่างฟังก์ชันสำคัญของดอส

ฟังก์ชัน
ฟังก์ชันการทำงาน
รายละเอียด
01h
อ่านแป้นพิมพ์
รอจนกระทั่งมีการพิมพ์อักขระหนึ่งตัวจากแป้นพิมพ์ และแสดงอักขระบนจอภาพรหัสแอสกีของอักขระนั้นจะเก็บอยู่ในรีจิสเตอร์ al ปุ่ม Ctrl-Break เป็นปุ่มยกเลิกการทำงานของฟังก์ชัน
02h
แสดงอักขระทางจอภาพ
นำรหัสแอสกีของอักขระจากรีจิสเตอร์ DL ไปแสดงผลทางจอภาพที่ตำแหน่งเคอร์เซอร์ปัจจุบัน
05h
พิมพ์อักขระทางเครื่องพิมพ์
นำรหัสแอสกีของอักขระซึ่งเก็บอยู่ในรีจิสเตอร์ DL ไปพิมพ์ออกทางเครื่องพิมพ์
07h
อ่านแป้นพิมพ์โดยไม่แสดงอักขระ
รอรับอักขระจากแป้นพิมพ์ และเก็บไว้ในรีจิสเตอร์ AL โดยไม่แสดงอักขระนั้น ฟังก์ชันนี้ไม่รับปุ่ม Ctrl-Break เพื่อหยุดการทำงาน
08h
อ่านแป้นพิมพ์โดยไม่แสดงอักขระ
เช่นเดียวกับฟังก์ชันหมายเลข 7 หากแต่หยุดการทำงานของได้ด้วย ปุ่ม Ctrl-Break
09h
แสดงสายอักขระ
แสดงสายอักขระบนจอภาพ โดยใช้รีจิสเตอร์ ds:dx เป็นตัวชี้ตำแหน่งเริ่มต้นของสายอักขระ ฟังก์ชันจะอ่านสายอักขระมาพิมพ์จนกว่าจะพบรหัส $ แต่จะไม่พิมพ์รหัส $ บนจอภาพ
0ah
อ่านสายอักขระ
อ่านสายอักขระจากแป้นพิมพ์และแสดงผลบนจอภาพจนกว่าจะกดปุ่ม Enter
4ch
กลับสู่ดอส
จบการทำงานของโปรแกรมและกลับสู่ดอส ค่าในรีจิสเตอร์ AL จะใช้เก็บรหัสการจบโปรแกรมซึ่งสามารถตรวจสอบได้ด้วยคำสั่ง if errorlevel ของ ดอส

ฟังก์ชัน 01h
เข้า: ah = 01h
ออก: al = รหัสแอสกี
หมายเหตุ: การทำงานของฟังก์ชันจะไม่เปลี่ยนแปลงค่าในรีจิสเตอร์ ah,bx,cx,dx,si,di, bp,cs,ds,es,ss และ แฟล็ก
ตัวอย่าง: ตามหลักการใช้ฟังก์ชันของดอสที่กล่าวไปแล้วว่า ให้กำหนดหมายเลขฟังก์ชันไว้ในรีจิสเตอร์ ax และใช้คำสั่ง int 21h การใช้ฟังก์ชัน 1 เพื่ออ่านการกดแป้นพิมพ์จึงมีเพียง 2 คำสั่งดังนี้

mov ah,1
int 21h

ฟังก์ชัน 01h จะรอการกดอักขระจากแป้นพิมพ์หนึ่งตัว แล้วแสดงอักขระนั้นบนจอภาพและจะนำรหัสแอสกีของอักขระนั้นไปไว้ที่รีจิสเตอร์ al

รหัส cr จะทำให้เคอร์เซอร์เลื่อนไปอยู่ซ้ายสุดหรือคอลัมน์แรกของบรรทัด ส่วนรหัส lf จะทำให้เคอร์เซอร์เลื่อนลงมาหนึ่งบรรทัด รวมกันเท่ากับการขึ้นบรรทัดใหม่ ชุดคำสั่งต่อไปนี้แสดงการพิมพ์ข้อความและขึ้นบรรทัดใหม่โดยใช้รหัสทั้งสอง

mov ah,2
mov dl,'o'
int 21h
mov dl,'h'
int 21h
mov dl,0dh
int 21h
mov dl, 0ah
int 21h

ฟังก์ชัน 02h
เข้า: ah = 02h
dl = รหัสแอสกีที่จะแสดงผล
ออก: ไม่มี
หมายเหตุ: การทำงานของฟังก์ชันจะไม่เปลี่ยนแปลงค่าในรีจิสเตอร์ใด
ตัวอย่าง: ฟังก์ชัน 2 กำหนดให้ใส่รหัสแอสกีของอักขระที่ต้องการแสดงผลไว้ในรีจิสเตอร์ dl หากต้องการแสดงอักขระ 'A' ซึ่งมีรหัสแอสกีเท่ากับ 41h ต้องใช้คำสั่งดังนี้

mov ah,2
mov dl,41h
int 21h
ฟังก์ชัน 09h
เข้า: ah = 09h
ds = เซกเมนต์ของหน่วยความจำที่เก็บสายอักขระ
dx = ค่าออฟเซ็ตของหน่วยความจำที่เก็บสายอักขระ
ออก: ไม่มี
หมายเหตุ: การทำงานของฟังก์ชันจะไม่เปลี่ยนแปลงค่าในรีจิสเตอร์ใด
ตัวอย่าง: ฟังก์ชัน 9 กำหนดให้ใส่ออฟเซ็ตของสายอักขระที่ต้องการส่งไปแสดงผลไว้ในรีจิสเตอร์ dx ออฟเซ็ตของสายอักขระจะอ้างอิงกับเซกเมนต์ข้อมูลเสมอ (ผ่านรีจิสเตอร์ ds) ตัวอย่างเช่นในเซกเมนต์ข้อมูลมีการกำหนดตัวแปรสายอักขระ "Assembly language program" ดังนี้


.data
: :
: :
msg db 'Assembly language program$'
: :

ชุดคำสั่งซึ่งทำหน้าที่พิมพ์ข้อความในตัวแปร msg จะเป็นดังนี้

mov ax,@data
mov ds,ax
: :
: :
mov dx, offset msg
mov ah,9
int 21h
ฟังก์ชัน 0AH
เข้า: ah = 0ah
ds = เซกเมนต์ของหน่วยความจำที่ใช้เก็บสายอักขระ
dx = ค่าออฟเซ็ตของหน่วยความจำที่ใช้เก็บสายอักขระ
ออก: ไม่มี
หมายเหตุ: การทำงานของฟังก์ชันจะไม่เปลี่ยนแปลงค่าในรีจิสเตอร์ใด
ตัวอย่าง: ฟังก์ชัน 0ah กำหนดให้ใช้ ds:dx ชี้ไปยังหน่วยความจำที่ใช้เป็นบัฟเฟอร์เก็บสายอักขระ ผู้เขียนโปรแกรมจะต้องใส่ตัวเลขบ่งบอกจำนวนอักขระที่จะยอมให้ป้อนได้ (นับรวมทั้งปุ่ม enter ด้วย) ไว้ที่ไบต์แรกของบัฟเฟอร์ ส่วนไบต์ที่สองของบัฟเฟอร์ให้กันเนื้อที่ไว้ เนื่องจากฟังก์ชันจะนับจำนวนอักขระที่ผู้ใช้ป้อนเข้ามา แล้วนำค่ามาเก็บที่ไบต์ที่สองนี้เมื่อจบสิ้นการทำงาน ฟังก์ชันจะจบการทำงานเมื่อกดปุ่ม enter และยังนำรหัสแอสกีของ enter (รหัส 0dh) ใส่ต่อท้ายอักขระตัวสุดท้ายที่ป้อนจากแป้นพิมพ์

.data
: :
maxlen db 30h
charin db ?
strbuff db 30 dup (20h)
: :
ชุดคำสั่งซึ่งทำหน้าที่รับสายอักขระจะเป็นดังนี้

.code
mov ax,@data
mov ds,ax
: :
: :
mov dx, offset maxlen
mov ah,0ah
int 21h

ตัวอย่างโปรแกรม
โปรแกรม UPCASE.ASM ตามรูปที่ 4.5 เป็นโปรแกรมอ่านสายอักขระจากแป้นพิมพ์และนำมาแปลงเป็นอักษรตัวใหญ่ โปรแกรมจะถือว่าผู้ใช้ต้องป้อนอักษรตัวเล็ก และจะนำรหัสแอสกีของอักษรนั้นมาลบด้วยค่า 20H โปรแกรมนี้จะไม่ตรวจสอบก่อนว่ารหัสก่อนที่จะนำมาลบ เป็นอักษรตัวเล็กหรือไม่ หากมีการป้อนอักขระอื่นเข้ามา โปรแกรมจะนำค่าไปลบด้วย 20H เสมอ ทำให้อาจได้อักขระอื่นที่ไม่ใช่ อักษรตัวใหญ่ ภายในโปรแกรมมีการใช้ฟังก์ชันดอสหลายฟังก์ชันคือฟังก์ชัน หมายเลข 2, 9 และ 0AH

;--------------------------------------
; upcase.asm
; read string from keyboard and change
; to upper case (undetect errors)
;--------------------------------------
;
dosseg
.model small

;reserved space for satck
.stack 100h

; variable and constant
.data
max_len db 25h
inp_len db ?
str_buff db 26h dup (20h)
msg_out1 db 'input string : $'
msg_out2 db 0dh,0ah,'upper case : $'
;
;start of program
;
.code
; init data segment
start: mov ax,@data
mov ds,ax

; display input message
mov ah,9
mov dx,offset msg_out1
int 21h

; read string
mov dx,offset max_len
mov ah,0ah
int 21h

; display output message
mov ah,9
mov dx, offset msg_out2
int 21h

; prepare pointer and counter
mov bx, offset inp_len
mov cl,[bx]
inc bx

; convert to upper case and display
next_char: mov ah,2
mov dl,[bx]
sub dl,20h
int 21h
inc bx
dec cl
jnz next_char

; return to dos with errorlevel 0
mov ax,4c00h
int 21h

end start

รูปที่ 4.5 โปรแกรม upcase.asm




การสร้างแฟ้ม UPCASE.EXE ให้เรียกใช้ MASM และ LINK ดังนี้


C:\>masm upcase;
microsoft (r) macro assembler version 5.00
copyright (c) microsoft corp 1981-1985, 1987. all rights reserved.


50850 + 406270 bytes symbol space free

0 warning errors
0 severe errors

c:\>link upcase;

microsoft (r) segmented-executable linker version 5.13
copyright (c) microsoft corp 1984-1991. all rights reserved.


เมื่อเรียกโปรแกรม upcase โปรแกรมจะรอให้ป้อนอักขระ และแปลงอักขระนั้นไปเป็นตัวใหญ่ดังตัวอย่างต่อไปนี้


C:\>upcase
input string : please convert it
upper case : PLEASE CONVERT IT

มาโครแอสเซมเบลอร์

ในหัวข้อนี้จะแสดงตัวอย่างการใช้งานเครื่องมือดังกล่าวโดยใช้ตัวอย่างโปรแกรม upcase.asm จากบทที่แล้ว เครื่องมือที่จะกล่าวถึงในที่นี้ได้แก่

· MASM
· LINK
การใช้ MASM
MASM จะนำแฟ้ม .asm มาสร้างเป็นแฟ้มรหัสภาษาเครื่องนามสกุล .obj การใช้คำสั่ง MASM มีรูปแบบดังนี้คือ

masm ค่าเผื่อเลือก แฟ้ม .asm, [แฟ้ม .obj], [แฟ้ม .lst], [แฟ้ม .crf]

หากต้องการเฉพาะแฟ้ม .obj อย่างเดียวให้ใช้เครื่องหมายอัตภาคปิดท้ายชื่อแฟ้มดังนี้

masm upcase;

หากต้องการแฟ้ม .obj, lst และ .crf โดยยังคงชื่อแฟ้มไว้ตามชื่อแฟ้ม .asm ให้ป้อนเครื่องหมายจุลภาคโดยไม่ใส่ชื่อแฟ้มตามตัวอย่าง

masm upcase,,,

หากเรียกใช้ MASM แปลโปรแกรมโดยไม่กำหนดพารามิเตอร์เพิ่มเติม MASM จะถามถึงชื่อแฟ้มที่ต้องการสร้างดังนี้


c:\>masm upcase.asm
Microsoft (r) macro assembler version 5.00
Copyright (c) microsoft corp 1981-1985, 1987. All rights reserved

Object filename [UPCASE.OBJ]:
Source listing [NUL.LST]: UPCASE.LST
Cross-reference [NUL.CRF]:

50850 + 406270 bytes symbol space free

0 Warning Errors
0 Severe Errors






แฟ้ม .lst
แฟ้ม upcase.lst ที่ได้จากการแปลโปรแกรม upcase.asm จะมีสามหน้า หน้าแรกและหน้าที่สองบรรจุคำสั่งที่กำกับด้วยรหัสภาษาเครื่องและหมายเลขบรรทัดไว้ดังรูปที่ 5.1 ตัวอย่างเช่นในบรรทัดที่ 33 มีตัวเลข 8e d8 ซึ่งเป็นรหัสคำสั่ง mov ds,ax ส่วนในบรรทัดที่ 37 มีรหัส ba 0028 R ซึ่งเป็นรหัสของคำสั่ง mov dx
รหัส 0028 R หมายถึงค่าที่ต้องรอการคำนวณภายหลัง ในที่นี้คือค่าออฟเซ็ตของตัวแปร msg_out1 ในขั้นของการลิงค์จะมีการคำนวณตำแหน่งออฟเซ็ตที่แท้จริงของ msg_out1 และนำมาแทนค่า R

Microsoft (R) Macro Assembler Version 5.00 8/19/96 15:22:13
Page 1-1


1 ; upcase.asm
2 ; read string from keyboard and change
3 ; to upper case (undetect errors)
4 ;--------------------------------------
5 ;
6 dosseg
7 .model small
8
9 ;reserved space for satck
10 0100 .stack 100h
11
12 ;variable and constant
13 0000 .data
14 0000 25 max_len db 25h
15 0001 ?? inp_len db ?
16 0002 0026[ str_buff db 26h dup (20h)
17 20
18 ]
19
20 0028 69 6E 70 75 74 20 73 msg_out1 db 'input string : $'
21 74 72 69 6E 67 20 3A
22 20 24
23 0038 0D 0A 75 70 70 65 72 msg_out2 db 0dh,0ah,'upper case : $'
24 20 63 61 73 65 20 20
25 20 3A 20 24
26
27 ;
28 ;start of program
29 ;
30 0000 .code
31 ; init data segment
32 0000 B8 ---- R start: mov ax,@data
33 0003 8E D8 mov ds,ax
34
35 ; display input message
36 0005 B4 09 mov ah,9
37 0007 BA 0028 R mov dx,offset msg_out1
38 000A CD 21 int 21h
39
40 ; read string
41 000C BA 0000 R mov dx,offset max_len
42 000F B4 0A mov ah,0ah
43 0011 CD 21 int 21h
44
45 ; display output message
46 0013 B4 09 mov ah,9
47 0015 BA 0038 R mov dx, offset msg_out2
48 0018 CD 21 int 21h
49
50 ; prepare pointer and counter
51 001A BB 0001 R mov bx, offset inp_len
52 001D 8A 0F mov cl,[bx]
53 001F 43 inc bx
54
55 ; convert to upper case and display
56 0020 B4 02 next_char: mov ah,2
57 0022 8A 17 mov dl,[bx]
58 0024 80 EA 20 sub dl,20h
59 0027 CD 21 int 21h
60 0029 43 inc bx
61 002A FE C9 dec cl
62 002C 75 F2 jnz next_char
63
64 ; return to dos with errorlevel 0
65 002E B8 4C00 mov ax,4c00h
66 0031 CD 21 int 21h
67
68 0033 end start
69

รูปที่ 5.1 แฟ้ม UPCASE.LST


หน้าที่สามของแฟ้ม upcase.lst เป็นข้อมูลเกี่ยวกับเซกเมนต์และการใช้ตัวแปร ตลอดจนขนาดของตัวโปรแกรมดังแสดงในรูปที่ 5.2
Microsoft (R) Macro Assembler Version 5.00 8/19/96 15:22:13
Symbols-1


Segments and Groups:

N a m e Length Align Combine Class

DGROUP . . . . . . . . . . . . . GROUP
_DATA . . . . . . . . . . . . 004A WORD PUBLIC 'DATA'
STACK . . . . . . . . . . . . 0100 PARA STACK 'STACK'
_TEXT . . . . . . . . . . . . . 0033 WORD PUBLIC 'CODE'

Symbols:

N a m e Type Value Attr

INP_LEN . . . . . . . . . . . . L BYTE 0001 _DATA

MAX_LEN . . . . . . . . . . . . L BYTE 0000 _DATA
MSG_OUT1 . . . . . . . . . . . . L BYTE 0028 _DATA
MSG_OUT2 . . . . . . . . . . . . L BYTE 0038 _DATA

NEXT_CHAR . . . . . . . . . . . L NEAR 0020 _TEXT

START . . . . . . . . . . . . . L NEAR 0000 _TEXT
STR_BUFF . . . . . . . . . . . . L BYTE 0002 _DATA Length = 0026

@CODE . . . . . . . . . . . . . TEXT _TEXT
@CODESIZE . . . . . . . . . . . TEXT 0
@DATASIZE . . . . . . . . . . . TEXT 0
@FILENAME . . . . . . . . . . . TEXT upcase


61 Source Lines
61 Total Lines
21 Symbols

50850 + 406270 Bytes symbol space free

0 Warning Errors
0 Severe Errors


รูปที่ 5.2 ข้อมูลทั่วไปกำกับท้ายโปรแกรม


การใช้ link
แฟ้ม upcase.obj เมื่อนำไปผ่านโปรแกรม LINK จะได้แฟ้ม upcase.exe ที่สามารถนำไปใช้งานได้ คำสั่ง LINK มีรูปแบบการใช้งานดังนี้คือ

masm /ค่าเผื่อเลือก แฟ้ม .asm, [แฟ้ม .obj], [แฟ้ม .lst], [แฟ้ม .crf]

หากต้องการเฉพาะแฟ้ม .EXE อย่างเดียวให้ใช้เครื่องหมายอัตภาคปิดท้ายชื่อแฟ้มดังนี้

link upcase;

หากต้องการให้สร้างชื่อแฟ้มตามชื่อที่กำหนดไว้โดยตัวโปรแกรม LINK เองให้ป้อนเครื่องหมายตามตัวอย่าง

link upcase,,,;

หากเรียกใช้ LINK แปลงโปรแกรมโดยไม่กำหนดพารามิเตอร์เพิ่มเติม LINK จะถามถึงชื่อแฟ้มที่ต้องการสร้างและแฟ้มอินพุตดังนี้

C:\>link upcase

Microsoft (R) Segmented-Executable Linker Version 5.13
Copyright (C) Microsoft Corp 1984-1991. All rights reserved.

Run File [UPCASE.EXE]:
List File [NUL.MAP]:
Libraries [.LIB]:
Definitions File [NUL.DEF]:

คำสั่งการโอนย้ายข้อมูล

· คำสั่ง MOV
การโอนย้ายข้อมูลระหว่างรีจิสเตอร์กับรีจิสเตอร์
การโอนย้ายข้อมูลกับหน่วยความจำ
การกำหนดค่าคงที่ให้กับหน่วยความจำ
· รูปแบบคำสั่ง MOV

MOV ปลายทาง , ต้นทาง

MOV reg , reg
MOV reg , mem
MOV mem , reg
MOV reg , imm
MOV mem , imm

*หมายเหตุ reg : รีจิสเตอร์
mem : ตำแหน่งหน่วยความจำ
imm : immediate (ค่าคงที่)
























ข้อจำกัดของคำสั่ง MOV

· โอเปอร์แรนด์ทั้งสองตัวต้องมีขนาดเท่ากัน
· ไม่สามารถคัดลอก
ค่าคงที่(immediate) ไปยังเซกเมนต์รีจิสเตอร์ได้โดยตรง
ข้อมูลจากหน่วยความจำไปยังหน่วยความจำได้โดยตรง
· ในการคัดลอกค่าคงที่ไปยังหน่วยความจำต้องระบุขนาดของ
หน่วยความจำด้วย


ตัวอย่างการใช้คำสั่ง MOV

MOV AX , 100h กำหนดค่า 100h ให้กับ AX จาก
MOV BX , AX นั้นคัดลอกไปให้ BX และ DX
MOV DX , BX


MOV AX , 1234h กำหนดค่า 1234h ให้กับ AX และค่า
MOV DX , 5678h 5678h ให้กับ DX จากนั้นคัดลอก
MOV AL , DL ค่าใน DL ไปให้ AL และ DH
MOV BH, DH ไปให้ BH


















ตัวอย่างการใช้คำสั่ง MOV


MOV AX , 100h กำหนดค่า 100h ให้กับ AX จากนั้นคัด
MOV [100h] , AX ลอกข้อมูลจาก AX ไปยังหน่วยความจำ
MOV BX , [100h] ตำแหน่งที่ DS: 100h และคัดลอกข้อมูล
กลับมายัง BX





กำหนดค่า 10h แบบไบต์ให้กับ
MOV BYTE PTR[200h] , 10h หน่วยความจำที่ DS: 200h
MOV WORD PTR[300h] , 10h และแบบเวิร์ดที่ DS: 300h






MOV AX , 2300h กำหนดค่า 2300h ให้กับ DS โดย
MOV DS , AX ผ่านทาง AX
















การโอนย้ายข้อมูลระหว่างรีจิสเตอร์

· การโอนย้ายข้อมูลระหว่างรีจิสเตอร์สามารถทำได้ถ้าขนาดของ
รีจิสเตอร์ทั้งคู่เท่ากัน


· คู่รีจิสเตอร์ 16 บิต กับ 8 บิต



MOV AX , 1000h

AX AH AL

1000h 10h 00h


MOV AL , 3Ah

AX AH AL

1034h 10h 3Ah


MOV AH , AL

AX AH AL

3A3Ah 3Ah 3Ah


MOV AX , 234h

AX AH AL

234h 02h 34h



การโอนย้ายข้อมูลกับหน่วยความจำ

· การระบุตำแหน่งในหน่วยความจำ
โดยทั่วไป ในการระบุตำแหน่งในหน่วยความจำเราจะระบุเฉพาะ
ออฟเซ็ตเท่านั้น โดยออฟเซ็ตที่ระบุจะถูกนำไปประกอบกับค่าใน
เซ็กเมนต์ รีจิสเตอร์ที่เหมาะสม เช่น ในการอ้างถึงข้อมูลออฟเซ็ต
จะถูกนำไปประกอบกับ DS เป็นต้น

· ตัวอย่าง








MOV AX , 6789h
DS : 100h
MOV DX , 1234h
DS : 101h
MOV [100h] , AX
DS : 101h
MOV [102h] , DX

MOV [104h] , AH

MOV [105h] , DL

MOV BX , [104h]

MOV CX , [103h]

MOV [106h] , CL















MOV [100h] , AX

67 89
89h
DS : 100h
DS : 101h
67h
MOV [102h] , DX
DS : 102h
34h
12 34
12h
67h
MOV [104h] , AH
34h
67


MOV [105h] , DL

34



MOV BX , [104h] 34 67



MOV CX , [103h] 67 12


















การโอนย้ายข้อมูลกับหน่วยความจำ

1. ข้อสังเกตในการจัดเรียงลำดับไบต์ของข้อมูล
1.1 สังเกตว่าในการเก็บค่าในหน่วยความจำเมื่อเราเก็บค่าเป็น 16 บิต การ
เรียงไบต์ในหน่วยความจำจะเก็บค่าในไบต์ที่มีนัยสำคัญสูงไว้ในไบต์ที่มี
แอดเดรสสูงกว่า และไบต์ที่มีนัยสำคัญต่ำไว้ในแอดเดรสที่มีแอดเดรส
ต่ำกว่า

1.2 เราเรียกว่าเป็นการเรียงแบบ little endian การเรียงข้อมูลแบบนี้ใช้ในหน่วยประมวล
ผลตระกูล Intel

1.3 ในหน่วยประมวลผลตระกูลอื่นเช่น SPARC หรือ MIPS จะเรียงไบต์
กลับกันการเรียงอีกแบบนี้เราเรียกว่าการเรียงแบบ big endian
2. เราสามารถระบุออฟเซ็ตของหน่วยความจำทางอ้อมได้โดยผ่านทางรีจิสเตอร์ BX
AX = ?

MOV AX , 102h

MOV BX , 100h

DS : 100h
02h MOV CX , 4004h
01 04
BX
DS : 101h
01h MOV DX , 1201h
04h
DS : 102h
MOV [BX] , AX
10h
01 00
AXMOV [BX+2] , CX
00h
01h MOV [BX+3] , DX

MOV [BX+4] , BX

MOV BX , [102h]

MOV AX , [BX]

การกำหนดค่าให้กับหน่วยความจำ

1. ลองสังเกตคำสั่งต่อไปนี้
MOV [100h] , 10h

2. การคัดลอกค่าไปยังหน่วยความจำจะเป็นแบบ
§ 16 บิต (คัดลอก 001h) หรือ
§ 8 บิต (คัดลอก 10h)

3. ในการเขียนค่าคงที่ลงในหน่วยความจำเราจะต้องระบุขนาดของหน่วยความจำด้วย
MOV WORD PTR [100h] , 10h
MOV BYTE PTR [100h] , 10h


4. สังเกตว่าความกำกวมนี้ไม่เกิดในกรณีของ
MOV [100h] , AX


สรุปการโอนย้ายข้อมูล

ตำแหน่งต้นทาง
ตำแหน่งปลายทาง

General register

Segment register

Memory location

Constant

General register

Segment register

Memory location

Constant

Yes

Yes

Yes

Yes

Yes

No

Yes

No


Yes

Yes

No

Yes

No

No

No

No







แบบฝึกหัด

1. ถ้าหากก่อนทำคำสั่ง MOV ค่าต่างๆเป็นไปตามที่กำหนด หลังจากทำคำสั่ง MOV ค่าต่างๆจะเป็นอย่างไร จงเติมค่าในที่ว่างที่กำหนด
ก่อนทำคำสั่ง
คำสั่ง
หลังทำคำสั่ง

BX : FF 75

MOV BX , CX

BX :=

CX : 01 A2


CX :=

AX : 01 A2

MOV AX , 100

AX


Value DW -1


DX : FF 75

MOV DX , Value

DX :=



Value :=

AX : 01 4B

MOV AH , 0

AX :=

AL : 64

MOV AL , -1

AL :=

























เฉลยแบบฝึกหัด

2. ถ้าหากก่อนทำคำสั่ง MOV ค่าต่างๆเป็นไปตามที่กำหนด หลังจากทำคำสั่ง MOV ค่าต่างๆจะเป็นอย่างไร จงเติมค่าในที่ว่างที่กำหนด
ก่อนทำคำสั่ง
คำสั่ง
หลังทำคำสั่ง

BX : FF 75

MOV BX , CX

BX : = 01 A2

CX : 01 A2


CX : = 01 A2

AX : 01 A2

MOV AX , 100

AX : = 01 00


Value DW -1


DX : FF 75

MOV DX , Value

DX : = -1



Value : = -1

AX : 01 4B

MOV AH , 0

AX : = 00 4B

AL : 64

MOV AL , -1

AL : = -1

Bit Shift

การกระทำระดับบิต

การจัดการกับข้อมูลที่เราได้ศึกษาในบทก่อน ๆ นั้นมีหน่วยย่อยในการจัดการเป็นไบต์ โดยเราไม่สามารถจัดการข้อมูลที่มีขนาดย่อยกว่านั้นได้ แต่ในการทำงานจริงในบางครั้งรูปแบบของข้อมูลที่เราต้องจัดการจะอยู่ในรูปของบิต เราจึงใช้คำสั่งเกี่ยวกับการจัดการระดับบิตในการประมวลผลข้อมูลกลุ่มนี้ และในบางกรณีคำสั่งกระทำระดับบิตสามารถช่วยให้การคำนวณต่าง ๆ ทำได้ง่ายขึ้นด้วย
คำสั่งปฏิบัติการกับบิต
คำสั่งที่สามารถปฏิบัติการกับบิตในรีจิสเตอร์กับหน่วยความจำ แบ่งออกเป็น 3 พวก คือ คำสั่งพวก logical , shift และ rotate ดังตาราง

ตาราง คำสั่งปฏิบัติการกับบิต
Mnemonic
Assembler Format
Flags
OF DF IF TF SF ZF AF PF CF


AND
OR
XOR
NOT
TEST


AND destination,source
OR destination,source
XOR destination,source
NOT destination
TEST destination,source

LOGICAL
0 - - - * * ? * 0
0 - - - * * ? * 0
0 - - - * * ? * 0
- - - - - - - - -
0 - - - * * ? * 0



SAL/SHL
SAR
SHR


SAL destination,count
SAR destination,count
SHR destination,count

SHIFT
* - - - * * ? * *
* - - - * * ? * *
* - - - 0 * ? * *



ROL
ROR
RCL
RCR



ROL destination,count
ROR destination,count
RCL destination,count
RCR destination,count

ROTATE
* - - - - - - - *
* - - - - - - - *
* - - - - - - - *
* - - - - - - - *
Note: * means changed,- means unchanged,? means undefined


คำสั่งทางตรรกศาสตร์
คำสั่งในกลุ่มนี้เป็นคำสั่งประมวลผลข้อมูลระดับบิต โดยจะนำค่าในแต่ระบิตของข้อมูลมาประมวลผลทางตรรกศาสตร์ คำสั่งในกลุ่มนี้ได้แก่ คำสั่ง AND คำสั่ง OR คำสั่ง XOR และคำสั่ง NOT รูปแบบการใช้งานของคำสั่ง AND คำสั่ง OR และคำสั่ง XOR จะมีลักษณะเหมือนกัน คือจะรับโอเปอร์แรนด์สองตัว และจะนำข้อมูลในโอเปอร์แรนด์ตัวแรกมากระทำกับข้อมูลตัวที่สอง และจะเก็บผลลัพธ์ของการกระทำนั้นในโอเปอร์แรนด์ตัวแรก ส่วนในกรณีของคำสั่ง NOT จะรับโอเปอร์แรนด์ตัวเดียว และจะทำการกลับค่าในบิตแล้วเก็บผลลัพธ์ลงในโอเปอร์แรนด์ตัวนั้นเลย ตารางค่าความจริงของการกระทำทางตรรกศาสตร์เป็นดังตารางที่ 1

A B
A and B A or B A xor B not B
0 0
0 0 0 1
0 1
0 1 1 0
1 0
0 1 1 1
1 1
1 1 0 0
ตารางที่ 1 ค่าของการกระทำทางตรรกศาสตร์

คำสั่ง AND
คำสั่งนี้จะนำบิตแต่ละบิตมากระทำลอจิก AND กันโดยผลลัพธ์จะเก็บใน destination ค่าของ destination อาจเป็นค่าในหน่วยความจำหรือรีจิสเตอร์ก็ได้ ส่วนค่าของ source จะเป็นค่าในรีจิสเตอร์ หน่วยความจำ หรือการอ้างแอดเดรสแบบ immediate ก็ได้ ( ผลลัพธ์ของคำสั่ง AND จะมีบิตที่เป็น 1 เมื่อบิตของข้อมูลตัวตั้งทั้งสองตัวมีค่าเป็น 1 ดังตารางที่ 1)
รูปแบบของคำสั่งเป็นดังนี้

AND destination,source

ภาษาแอสเซมบลี
การทำงาน

AND AL,BL
AND CX,DX
AND CL,33H
AND DI,4FFFH
AND AX,[DI]



AL = AL AND BL
CX = CX AND DX
CL = CL AND 33H
DI = DI AND 4FFFH
นำ AX มา AND กับเวิร์ดข้อมูลที่อยู่ในเซกเมนต์หน่วยความจำข้อมูลที่ชี้ตำแหน่งโดย DI

ตัวอย่าง จงเขียนคำสั่งเคลียร์บิตเครื่องหมายในรีจิสเตอร์ AL
วิธีทำ ใช้คำสั่ง AND โดยนำข้อมูล 01111111b = 7FH ไป AND เขียนคำสั่งได้
ดังนี้
AND AL,7FH

ตัวอย่าง จงแสดงผลลัพธ์ต่อไปนี้
MOV BL,35H
AND BL,0FH
วิธีทำ
35H 0 0 1 1 0 1 0 1
0FH 0 0 0 0 1 1 1 1
05H 0 0 0 0 0 1 0 1
แฟลกต่าง ๆ เป็นดังนี้ SF = 0, ZF = 0, PF = 1, CF = OF = 0

ตัวอย่าง ถ้าหากค่าในรีจิสเตอร์ AL เก็บค่ารหัส ASCII ของเลข 7 เราสามารถใช้คำสั่ง
AND เปลี่ยนค่าในรีจิสเตอร์ AL ให้เป็นเลข 7 ฐานสิบได้ดังตัวอย่างคำสั่งต่อไปนี้
ค่าในรีจิสเตอร์ AL 0011 0111
ค่าในรีจิสเตอร์ BL 0000 1111
หลังจากทำคำสั่ง AND AL,BL ค่าในริจิสเตอร์ AL จะมีค่าเป็น 0000 0111 ซึ่งค่านี้จะมีค่าเท่ากับเลข 7 ในฐานสิบ

คำสั่ง AND จะมีผลต่อแฟลก เราสามารถนำคำสั่งนี้มาทำงานร่วมกับคำสั่งกระโดดได้ อย่างเช่นถ้าต้องการทดสอบว่าค่าในรีจิสเตอร์เป็นศูนย์หรือไม่สามารถเขียนได้ดังนี้
AND DH,DH
JZ XXXX
….
XXXX: .…
ถ้าหาก ZF เป็น 1 หมายความว่าผลลัพธ์เป็นศูนย์ จะกระโดดไปทำงานที่ XXXX

คำสั่ง OR
คำสั่งนี้จะคล้ายกับคำสั่ง AND ค่าของ destination จะเป็นค่าในรีจิสเตอร์หรือหน่วยความจำก็ได้ ค่าของ source อาจเป็นค่าในรีจิสเตอร์ หน่วยความจำ หรือการอ้างแอดเดรสแบบ immediate การทำงานของคำสั่งนี้จะมีผลต่อแฟลกเช่นเดียวกับคำสั่ง AND
ถ้าต้องการใช้คำสั่งนี้ตรวจสอบว่าค่าใน BL เป็นศูนย์หรือไม่อาจทำได้โดย OR BL,0 โดยทำการ OR ค่าในรีจิสเตอร์ BL กับค่า 0 ถ้าหากผลลัพธ์เป็น 0 แฟลก ZF จะเป็น 1
คำสั่ง OR สามารถใช้เซ็ตบิตที่ต้องการได้โดยนำลอจิก 1 ไปทำการ OR
(ผลลัพธ์ของคำสั่ง OR จะมีบิตที่เป็น 1 เมื่อบิตของข้อมูลตัวตั้งตัวใดตัวหนึ่งหรือทั้งสองตัวมีค่าเป็น 1 ดังตารางที่ 1) รูปแบบของคำสั่งเป็นดังนี้

OR destination,source

ตัวอย่าง จงเขียนโปรแกรมเซ็ตบิตเครื่องหมายและบิตต่ำสุดของรีจิสเตอร์ AL
วิธีทำ ใช้คำสั่ง OR โดยนำค่า 10000001b = 81H ไป OR ซึ่งเขียนคำสั่งได้ดังนี้
OR AL,81H

ตัวอย่าง จงหาผลลัพธ์จากการกระทำต่อไปนี้
MOV AX,0504 ;AX = 0504
OR AX,0DA68H ;AX = DF6C
วิธีทำ
0504H 0000 0101 0000 0100
DA68H 1101 1010 0110 1000
DF6C 1101 1111 0110 1100
ค่าแฟลกต่าง ๆ จะเป็นดังนี้ SF =1, ZF = 0, PF = 1, CF = OF = 0
ค่า parity จะเช็กเฉพาะ 8 บิตล่างเท่านั้น

คำสั่ง XOR
คำสั่งนี้จะทำ exclusive-OR แบบบิตต่อบิต ถ้าบิตต่างกันผลลัพธ์จะเป็น 1 แต่ถ้าบิตเหมือนกันผลลัพธ์จะเป็น 0 ดังตารางที่ 1 คำสั่งนี้จะมีผลต่อแฟลกเช่นกัน คำสั่งนี้สามารถใช้ในการเปลี่ยนบิตได้ รูปแบบของคำสั่งเป็นดังนี้

XOR destination,source

ตัวอย่าง จงเปลี่ยนบิตเครื่องหมายของรีจิสเตอร์ DX
วิธีทำ ใช้คำสั่ง XOR โดยกระทำกับค่า 8000H ซึ่งเขียนคำสั่งได้ดังนี้
XOR DX,8000H

ตัวอย่าง จงหาผลลัพธ์จากการกระทำต่อไปนี้
MOV DH,54H
XOR DH,78H
วิธีทำ
54H 0 1 0 1 0 1 0 0
78H 0 1 1 1 1 0 0 0
2C 0 0 1 0 1 1 0 0
ค่าแฟลกต่าง ๆ จะเป็นดังต่อไปนี้ SF = 0, ZF = 0, PF = 0, CF = OF = 0

ตัวอย่าง คำสั่ง XOR สามารถใช้เคลียร์ค่าในรีจิสเตอร์ได้ อย่างเช่นถ้า AH = 45H เรา
สามารถเคลียร์ค่าในรีจิสเตอร์ได้โดยการทำคำสั่งต่อไปนี้
XOR AH,AH
วิธีทำ สิ่งที่เกิดขึ้นจะเป็นดังนี้
45H 01000101
45H 01000101
00 00000000
แฟลกต่าง ๆ จะเป็นดังนี้ SF = 0, ZF = 1, PF = 1,CF = OF = 0


คำสั่ง NOT
คำสั่ง NOT จะสลับบิตของโอเปอร์แรนด์จาก 0 เป็น 1 และ 1 เป็น 0 ดังตารางที่ 1
รูปแบบของคำสั่งเป็นดังนี้

NOT destination

ตัวอย่าง จงหาผลลัพธ์จากการกระทำต่อไปนี้
MOV AX,1234H
NOT AX ;AX = not(0001 0010 0011 0100)
;AX = (1110 1101 1100 1011)=0EDCBH

คำสั่ง TEST
คำสั่ง TEST จะทำงานเหมือนคำสั่ง AND ทุกประการ แต่ผลลัพธ์จากการ AND จะไม่เขียนค่าลงในโอเปอร์แรนด์ตัวแรก ผลจากการใช้คำสั่งนี้จะปรากฏในแฟลก เรานิยมใช้คำสั่งนี้ในการทดสอบว่าข้อมูลในบิตที่ต้องการมีค่าเป็น 1 หรือไม่ โดยเราจะพิจารณาจากแฟลกทด
คำสั่งนี้จะคล้ายกับคำสั่ง CMP แต่ต่างกันที่คำสั่ง TEST จะกระทำแบบบิตต่อบิตโดยทั่วไปแล้วคำสั่ง TEST จะตามด้วยคำสั่ง JZ (jump if zero) หรือ JNZ (jump if not zero) ในการใช้งานมักจะทกสอบทีละบิต โดยจะกระทำกับข้อมูลแบบ immediate

ตัวอย่าง
TEST AL,01
JNZ RIGHT
TEST AL,128
JNZ LEFT
นอกจากนี้คำสั่ง TEST ยังสามารถนำมาประยุกต์สร้างเป็นคำสั่งเลือกทำแบบหลาย ๆ ทางได้ อย่างเช่นในตัวอย่างต่อไปนี้จะทดสอบค่าในรีจิสเตอร์ AL ถ้าบิตที่ 0 เป็น 1 จะกระโดดไปที่ CASE_A ถ้าบิตที่ 1 เป็น 1 จะกระโดดไปที่ CASE_B
MOV AL,XXXX
TEST AL,0000 0001B
JNZ CASE_A
TEST AL,0000 0010B
JNZ CASE_B
…..
…..
CASE_A: …..
…..
CASE_B: …..

เราสามารถเปรียบเทียบการทำคำสั่ง TEST และคำสั่ง AND ได้ดังนี้
AH DL Z-flag
ก่อนทำคำสั่ง 01010011 10001100 ?
หลังจากทำคำสั่ง AND DL,AH
01010011 00000000 1
หลังจากทำคำสั่ง TEST DL,AH
01010011 10001100 1

จะเห็นว่าคำสั่งทั้งสองมีผลต่อแฟลก แต่คำสั่ง TEST จะไม่ทำให้ค่าผลลัพธ์ในรีจิสเตอร็เปลี่ยนแปลง



การประยุกต์ใช้งานคำสั่งทางตรรกศาสตร์
เราสามารถนำคำสั่งทางตรรกศาสตร์มาใช้ในการประมวลผลข้อมูลระดับบิตได้ จากตารางที่ 1 เราสามารถสร้างตารางที่ 2 ซึ่งแสดงผลของการใช้คำสั่งทางตรรกศาสตร์กับข้อมูลได้


B A and B A or B A xor B
0 0 A A
1 A 1 ~A

ตารางที่ 2 ผลของการใช้คำสั่งทางตรรกศาสตร์กับข้อมูล

จากตารางเราจะพบว่าถ้าเราต้องการให้บิตใดของข้อมูลมีค่าเป็น 1 โดยที่บิตอื่นมีค่าคงเดิม เราสามารถใช้คำสั่ง AND ได้ และถ้าเราต้องการจะทำให้บิตใดของข้อมูลมีค่าเป็น 0 โดยไม่มีผลกระทบกับแฟลกอื่น ๆ เราสามารถใช้คำสั่ง OR สำหรับคำสั่ง XOR เราจะใช้ในกรณีที่ต้องการกลับบิตของข้อมูลจาก 0 เป็น 1

ตัวอย่างการประยุกต์ใช้งานคำสั่งทางตรรกศาสตร์
โปรแกรมตัวอย่างต่อไปนี้จะเปลี่ยนบิตที่ 1 และ 2 ของ AL ให้มีค่าเป็น 0 (การนับบิตจะนับบิตที่มีนัยสำคัญต่ำสุดเป็นบิตที่ 0) และเปลี่ยนบิตที่ 4 และ 6 ให้มีค่าเท่ากับ 1 พร้อมทั้งกลับบิตที่ 3 ให้มีค่าตรงกันข้าม การทำงานคร่าว ๆ มีลักษณะดังรูปที่ 1

AL XXXX XXXX
AND 1111 1001
OR 0101 0000
XOR 0000 1000
RESULT X1X1 X00X
รูปที่ 1 ขั้นตอนการแปลงค่าของ AL

โปรมแกรมจะมีลักษณะดังนี้
AND AL,0F9H ;clear bit 1&2
OR AL,50H ;set bit 4&6
XOR AL,08H ;switch bit 3


คำสั่งเลื่อนข้อมูล
การเลื่อน Shifting ถือว่าเป็นประโยชน์อย่างยิ่งในการเขียนโปรแกรม อย่างเช่นถ้าจะตรวจสอบว่าข้อมูลที่มีอยู่เป็นเลขบวกหรือลบอาจใช้วิธีการเลื่อนค่าข้อมูลให้บิตเครื่องหมายออกมาอยู่ที่บิตแฟลกแล้วตรวจว่าเป็นลอจิก 1 หรือ 0 ก็สามารถทำให้บอกว่าข้อมูลที่มีอยู่เป็นเลขบวกหรือลบ คำสั่งเลื่อนข้อมูลจะมีโอเปอแรนด์สองตัว ตัวแรกจะเป็นข้อมูลที่จะเลื่อนเป็นจำนวนครั้งเท่าไร ถ้ามีการเลื่อนมากกว่าหนึ่งครั้งจะใช้รีจิสเตอร์ CL

การเลื่อนไปทางขวา
การเลื่อนแบบนี้จะใช้คำสั่ง SHR(Shift Right) โดยข้อมูลทุกบิตจะถูกเลื่อนไปทางขวาบิตที่ถูกเลื่อนออกไปจะถูกเก็บในบิตตัวทดและในการเลื่อนนั้นจะใส่ลอจิก 0 เข้าไป ดังรูป โดยรูปแบบของคำสั่งการเลื่อนบิตไปทางซ้าย SHL(Shift Left) จะมีลักษณะเหมือนคำสั่ง SHR เพียงแต่ย้ายข้อมูลไปทางซ้าย

ถ้าหากมีการทำคำสั่งต่อไปนี้

MOV BX,0FFFFH ;BX = FFFFH
SHR BX,1 ;เลื่อนรีจิสเตอร์ BX ไปทางขวาหนึ่งครั้ง

ผลลัพธ์ที่ได้จากการเลื่อนค่าของรีจิสเตอร์ BX จะเป็น 7FFFH และแฟลก CF เป็น 1 การทำงานของคำสั่ง SHR จะมีผลต่อแฟลก OF,SF,PF และ ZF ถ้าหากต้องการเลื่อนหลายครั้งจะต้องใส่รีจิสเตอร์ CX เก็บจำนวนครั้งที่เลื่อน อย่างเช่นต้องการเลื่อนข้อมูลใน BX จำนวน 3 ครั้ง ทำได้ดังต่อไปนี้

MOV CL,3
SHR BX,CL

ตัวอย่าง จงแสดงผลลัพธ์จากการทำคำสั่งต่อไปนี้
MOV AL,9AH
MOV CL,3
SHR AL,CL
วิธีทำ 9AH = 10011010
01001101 CF = 0 เลื่อนหนึ่งครั้ง
00100110 CF = 1 เลื่อนสองครั้ง
00010011 CF = 0 เลื่อนสามครั้ง
หลังจากทำคำสั่งแล้วจะได้ AL = 13H และ CF = 0

การเลื่อนไปทางขวาแบบคิดเครื่องหมาย
การเลื่อนแบบนี้จะใช้ในการคำนวณทางคณิตศาสตร์ โดยใช้คำสั่ง SAR(Shift Arithmetic Right) คำสั่งเลื่อนข้อมูลแบบนี้ บิตเครื่องหมายจะไม่มีการเปลี่ยนแปลง การทำงานของคำสั่งประเภทนี้แสดงได้ดังรูป และรูปของคำสั่งมีสองรูปแบบคือ

SAR destination,1
SAR destination,CL

รูปแสดงการทำงานของคำสั่ง SAR

การเลื่อนไปทางซ้ายแบบคิดเครื่องหมาย
คำสั่ง SAL(Shift Arithmetic Left) ไม่เก็บค่าของบิตที่มีเครื่องหมาย แต่จะใส่ค่า 1 ในแฟลก OF ถ้ามีการเปลี่ยนเครื่องหมาย ทุกครั้งที่ปฏิบัติการคำสั่ง SAL บิต 0 จะมีค่า 0
และรูปของคำสั่งมีสองรูปแบบคือ

SAL destination,1
SAL destination,CL

คำสั่งหมุนข้อมูล
คำสั่งหมุนข้อมูล(rotate) จะใช้หมุนบิตข้อมูลในรูปแบบไบต์หรือเวิร์ด โดยจะอ้างข้อมูลในรีจิสเตอร์หรือหน่วยความจำ โดยจะหมุนข้อมูลไปทางซ้ายและทางขวา

การหมุนทางซ้าย(rotate left)
จะเลื่อนบิตข้อมูลในรีจิสเตอร์ไปทางซ้าย หรือเลื่อนจากบิตต่ำไปบิตสูงเป็นวงกลม โดยข้อมูลจากบิตสูงสุดจะถูกเลื่อนไปยังบิตต่ำ และบิตแฟลก CF ดังแสดงในรูป
คำสั่งที่ใช้เลื่อนข้อมูลมีสองคำสั่งคือ

ROL destination,1
ROL destination,CL

คำสั่งแรกจะหมุนข้อมูลทุกบิตไปทางซ้ายหนึ่งบิต ส่วนคำสั่งที่สองจะกำหนดจำนวนครั้งที่จะหมุนข้อมูลในรีจิสเตอร์ CL



รูปการทำงานของคำสั่ง ROL

การหมุนทางขวา(rotate right)
จะเลื่อนบิตข้อมูลทุกบิตไปทางขวาเป็นวงกลม โดยค่าในบิตต่ำสุดจะถูกเลื่อนไปยังบิตสูงสุด และบิตแฟลก CF ดังแสดงในรูป คำสั่งที่ใช้มีอยู่สองคำสั่งคือ

ROR destination,1
ROR destination,CL

คำสั่งแรกจะหมุนข้อมูลทุกบิตไปทางขวาหนึ่งครั้ง ส่วนคำสั่งที่สองจะหมุนข้อมูลทุกบิตเป็นจำนวนครั้งตามข้อมูลที่อยู่ในรีจิสเตอร์ CL



รูปแสดงการทำงานของคำสั่ง ROR

ตัวอย่าง จงใช้คำสั่ง ROL นับจำนวนบิตข้อมูลที่มีค่าลอจิก 1 ในรีจิสเตอร์ BX โดยไม่มีการ
เปลี่ยนแปลงค่าใน BX คำตอบที่ได้เก็บในรีจิสเตอร์ AX
วิธีทำ
XOR AX,AX ;ใช้ AX เป็นตัวนับบิต โดยเคลียร์ให้มีค่าเป็น 0
MOV CX,16 ;ใส่จำนวนครั้งที่จะหมุนข้อมูล
TOP:
ROL BX,1 ;หมุนข้อมูล1 ครั้ง
JNC NEXT ;ถ้าค่าใน CF ไม่เป็น 1 จะกระโดดไปที่ NEXT
INC AX ;ถ้าเป็น 1 ให้เพิ่มค่า AX
NEXT:
LOOP TOP ;ทำซ้ำเพื่อตรวจสอบบิตต่อไป

คำสั่งหมุนข้อมูลแบบผ่านตัวทด
คำสั่งประเภทนี้จะนำค่าในตัวทดมาหมุนด้วย ซึ่งมีทั้งแบบการหมุนทางซ้ายแบบผ่านตัวทด(Rotate through Carry Left) โดยใช้คำสั่ง RCL และการหมุนทางขวาแบบผ่านตัวทด(Rotate through Carry Right) โดยใช้คำสั่ง RCR
การหมุนทางซ้ายแบบผ่านตัวทดจะเลื่อนข้อมูลทุกบิตไปทางซ้าย โดยบิตสูงสุดจะถูกเลื่อนไปในบิตแฟลก CF และค่าในบิต CF จะถูกเลื่อนไปบิตต่ำสุดดังรูป รูปแบบของคำสั่งเป็นดังนี้

RCL destination,1
RCL destination,

รูปการทำงานของคำสั่ง RCL

การหมุนทางขวาแบบผ่านตัวทดจะเลื่อนข้อมูลทุกบิตไปทางขวาโดยบิตต่ำสุดจะถูกเลื่อนเข้าไปในบิต CF และค่าในบิต CF จะถูกเลื่อนไปบิตสูงสุดแสดงดังรูป รูปแบบของคำสั่งเป็นดังนี้
RCR destination,1
RCR destination,CL


รูปการทำงานของคำสั่ง RCR

ตัวอย่าง ถ้าค่าในรีจิสเตอร์ DH มีค่าเป็น 8AH บิตแฟลก CF เป็น 1 และค่าใน CL เป็น 3
จงหาค่าในรีจิสเตอร์ DH และ CF หลังจากทำคำสั่ง RCR DH,CL
วิธีทำ การทำงานต่าง ๆ สรุปได้ดังตารางต่อไปนี้
การทำงาน
CF
DH
ค่าเริ่มต้น
หลังจากหมุนหนึ่งครั้ง
หลังจากหมุนสองครั้ง
หลังจากหมุนสามครั้ง

1
0
1
0
10001010
11000101
01100010
10110001
ดังนั้นหลังจากทำคำสั่ง ค่าในรีจิสเตอร์ DH เป็น B1H
แบบฝึกหัดท้ายบท

1) จงคำนวณเลขต่อไปนี้
1.1) 1001 1000 AND 1111 0000
1.2) 1110 0110 AND 1100 1100
1.3) 0110 1001 OR 1111 0000
1.4) 0101 0110 OR 0101 1100
1.5) 1001 1001 XOR 0000 1111
1.6) 1010 0110 XOR 0101 0110

2) จงคำนวณเลขต่อไปนี้
2.1) FBh AND ACh
2.2) CDh AND 75h
2.3) 8Eh OR 91h
2.4) 7Fh OR F4h
2.5) 2Ah XOR D6h
2.6) 9Bh XOR DBh

3) จงแสดงผลลัพธ์ต่อไปนี้
MOV AX,1234H
AND AX,2345H MOV AL,25H
AND AL,0FH
MOV BL,0AAH
AND BL,80H

4) จงแสดงผลลัพธ์ต่อไปนี้
MOV AX,1234H
OR AX,2345H
MOV AL,25H
OR AL,0FH
MOV BL,55H
OR BL,80H



5) จงแสดงผลลัพธ์ต่อไปนี้
MOV AX,1234H
XOR AX,2345H
MOV AL,25H
XOR AL,0FH
MOV BL,15H
XOR BL,35H


6) จงแสดงผลลัพธ์จากการทำคำสั่งต่อไปนี้
DATA1 DW 7777H
TIMES EQU 4
MOV CL,TIMES ;CL = 04
SHR DATA1,CL
หลังจากทำคำสั่งแล้ว DATA1 จะมีค่าเป็นเท่าไหร่

7) จงขียนโปรแกรมนับจำนวนบิตที่มีค่าเป็นหนึ่งใน AX โดยจะให้ผลลัพธ์ใน BL

8) การใช้งานคำสั่งหมุนบิตที่ผ่านแฟลกทด
8.1) จงขียนการเลื่อนบิตของข้อมูลขนาด 32 บิตที่อยู่ในรีจิสเตอร์ DX,AX ไปทางซ้าย 1บิต
8.2) จงเขียนการคูณข้อมูลขนาด 48 บิตที่เก็บในรีจิสเตอร์ BX,DX และ AX ต่อเนื่องกัน
ด้วย 4
8.3) ขงเขียนการหารข้อมูลใน DX,AX ด้วย 2

9) จงเขียนส่วนของโปรแกรมที่จะคูณค่าในรีจิสเตอร์ AX ด้วย 10 โดย ไม่ใช้คำสั่ง MUL แต่สามารถใช้คำสั่ง shift และ add ได้

10) จงเขียนโปรแกรมที่แสดงค่ารหัสแอสกีของปุ่มที่รับจากผู้ใช้เป็นเลขฐานสอง โปรแกรมย่อย ที่แสดงข้อมูลเป็นรหัสเลขฐานสองใช้การเลื่อนบิตในการประมวลผล






เฉลยแบบฝึกหัดท้ายบท

1)
1.1) 1001 0000
1.2) 1100 0100
1.3) 1111 1001
1.4) 0101 1110
1.5) 1001 0110
1.6) 1111 0000

2)
2.1) A8
2.2) 45
2.3) 9F
2.4) FF
2.5) FC
2.6) 40

3) วิธีทำ
MOV AX,1234H
AND AX,2345H ;AX = (0001 0010 0011 0100) and (0010 0011 0100 0101)
;AX = (0000 0010 0000 0100)=0204H MOV AL,25H
AND AL,0FH ;AL = 05H
MOV BL,0AAH
AND BL,80H ;BL = 80h

4) วิธีทำ
MOV AX,1234H
OR AX,2345H ;AX = (0001 0010 0011 0100) and
(0010 0011 0100 0101)
;AX = (0011 0011 0111 0101)=3375H
MOV AL,25H
OR AL,0FH ;AL = 2FH
MOV BL,55H
OR BL,80H ;BL = 0D5H
5) วิธีทำ
MOV AX,1234H
XOR AX,2345H ;AX = (0001 0010 0011 0100) and
(0010 0011 0100 0101)
;AX = (0011 0001 0111 0001)=3171H
MOV AL,25H
XOR AL,0FH ;AL = 2AH
MOV BL,15H
XOR BL,35H ;BL = 20H

6) DATA1 จะมีค่าเป็น 0777

7) MOV BL,0
MOV CX,16 ;16 bits
PROCBITS:
TEST AX,1 ;test for last bit
JZ DOPROCBIT ;if last bit = 0 jump
INC BL
DOPROCBIT:
SHR AX,1 ;next bit
LOOP PROCBITS

8)
8.1)
CLC
RCL AX,1
RCL DX,1
8.2)
CLC
RCL AX,1
RCL DX,1
RCL BX,1
CLC
RCL AX,1
RCL DX,1
RCL BX,1

8.3)
CLC
RCR DX,1
RCR AX,1

9)
MOV BX,AX ;save content of AX in BX
MOV CL,2
SHL AX,CL ;AX < ------- AX*4
ADD AX,BX ;AX <------- AX*5
SHL AX,1 ;AX <------- AX*10

10)
.MODEL SMALL
.DOSSEG
.CODE
; Display Binary (input:AL)
DISPBIN PROC NEAR
PUSH AX
PUSH CX
PUSH DX
MOV AX,8
PRINTLOOP:
TEST AL,80H ;test for 1
JZ PRINTZERO
MOV DL,’1’
JMP PRINTIT
PRINTZERO:
MOV DL,’0’
PRINTIT:
MOV AH,2
INT 21H

SHL AL,1
LOOP PRINTLOOP
POP DX
POP CX
POP AX
RET
DISPBIN ENDP
START:
MOV AH,1
INT 21H

CALL DISPBIN

MOV AX,4C00H
INT 21H
END START

Number System

ระบบเลขจำนวน
ระบบเลขจำนวนที่เรารู้จักกันดีนอกจากระบบเลขฐานสิบแล้ว ก็ยังมีระบบอื่นที่ใช้ในชีวิตประจำวัน เช่นระบบเวลา คือ 60 วินาทีเท่ากับ 1 นาที , 60 นาทีเท่ากับ 1 ชั่วโมง และ 24 ชั่วโมงเท่ากับ 1 วัน หรือระบบการวัด เช่น 12 นิ้วเท่ากับ 1 ฟุต , 3 ฟุตเท่ากับ 1 หลา เป็นต้น
ตัวอย่างที่ 1
30 วินาที + 45 วินาที = 75 วินาที = 1 นาที 15 วินาที
25 นาที + 55 นาที = 80 นาที = 1 ชั่วโมง 20 นาที
1 ชั่วโมง 10 นาที - 30 นาที = 70 นาที - 30 นาที = 40 นาที
8 นิ้ว + 7 นิ้ว = 15 นิ้ว = 1 ฟุต 3 นิ้ว
ระบบเลขฐานสิบที่มีเลขโดด 10 ตัวคือ 0, 1, 2, ..., 9 และค่าของเลข ณ ตำแหน่งใดก็คือค่าของเลขโดด ณ ตำแหน่งนั้นคูณด้วยสิบ ยกกำลังของตำแหน่งนั้น
เช่น 12345 หมายความว่า ค่า 5 อยู่ในตำแหน่งหลักหน่วย (100)
ค่า 4 อยู่ในตำแหน่งหลักสิบ (101)
ค่า 3 อยู่ในตำแหน่งหลักร้อย (102)
ค่า 2 อยู่ในตำแหน่งหลักพัน (103)
และ ค่า 1 อยู่ในตำแหน่งหลักหมื่น (104)
เขียนเป็นผลบวกทางคณิตศาสตร์ได้
12345 = (1x104) + (2x103) + (3x102) + (4x101) + (5x100)
= 10000 + 2000 + 300 + 40 + 5
= 12345
จะเห็นว่าระบบเลขฐานสิบ จะมีการทดค่าไปอยู่ตำแหน่งต่อไปเมื่อถึงค่า 10 ทุกครั้งที่ครบ 10 ก็จะทดค่า 1 ไปที่ตำแหน่งทางซ้ายมือ
ตัวอย่างที่ 2
5 + 5 = 10
7 + 3 = 10
7 + 5 = 12
จากระบบเลขฐานสิบที่คุ้นเคยกันดี ก็จะใช้หลักการณ์เดียวกันมาทำความเข้าใจ กับระบบเลขฐานสอง ซึ่งเป็นระบบที่เครื่องคอมพิวเตอร์เข้าใจและประมวลผลได้ ระบบของเลขฐานสองมีเลขโดดอยู่สองตัวคือ 0 และ 1 และตำแหน่งของค่า 0 และ 1 ก็คือค่ากำลังของเลขฐานสอง การบวกลบก็ทำเช่นเดียวกันกับระบบเลขฐานสิบ เพียงแต่ว่าจะทดค่า 1 ไปในตำแหน่งถัดไปทางซ้ายมือเมื่อครบ 2

เช่น 101012 = (1x24) + (0x23) + (1x22) + (0x21) + (1x20)
= 16 + 0 + 4 + 0 + 1
= 2110

2.1 การเปลี่ยนค่าจากเลขฐานสิบเป็นเลขฐานสอง
ทำการหารเลขฐานสิบด้วยสองไปเรื่อยๆ จะได้ผลลัพธ์คือเศษที่มีค่า 0 หรือ 1 ตำแหน่งของเศษที่เกิดจากการหารก็คือกำลังของเลขฐานสอง กล่าวคือ เศษที่เกิดจากการหารด้วย 2 ครั้งแรก จะคูณด้วย 20 , เศษที่เกิดจากการหารด้วย 2 ครั้งที่ 2 จะคูณด้วย 21 เรื่อยไป
ตัวอย่างที่ 3 จะเปลี่ยนค่า 12310 เป็นเลขฐานสอง
2 1 2 3
6 1 เศษ 1
3 0 เศษ 1
1 5 เศษ 0
7 เศษ 1
8 เศษ 1
1 เศษ 1
0 เศษ 1
ดังนั้น 12310 = 1 1 1 1 0 1 1 2

2.2 การเปลี่ยนค่าจากเลขฐานสองเป็นเลขฐานสิบ
เลขฐานสิบที่ได้จากเลขฐานสอง มีค่าเท่ากับผลบวกของเลขโดด 0 หรือ 1 คูณด้วยค่าสองยกกำลังตำแหน่งที่ค่าของเลขโดด ของเลขฐานสองในทุกตำแหน่ง
ตัวอย่างที่ 4 จงเปลี่ยนค่า 1011012 ให้เป็นเลขฐานสิบ
1011012 = (1x25) + (0x24) + (1x23) + (1x22) + (0x21) + (1x20)
= 32 + 0 + 8 + 4 + 0 + 1
= 4510

2.3 การเปลี่ยนค่าเศษส่วนจากเลขฐานสิบเป็นเลขฐานสอง
การคิดเศษส่วนฐานสองก็คล้ายกับเลขจำนวนเต็มฐานสองเพียงแต่ค่าของกำลังจะเป็นค่าลบ คือตำแหน่งที่อยู่หลังจุดทศนิยมตำแหน่งแรกมีกำลัง –1 และตำแหน่งถัดไปทางขวามือของจุดทศนิยมเป็น –2 , -3 เป็นต้น
ตัวอย่างที่ 5 การเปรียบเทียบค่าเลขเศษส่วนฐานสองและเลขเศษส่วนฐานสิบ
เศษส่วนฐานสอง เศษส่วนฐานสิบ
.1 = 2-1 0.5
.01 = 2-2 0.25
.001 = 2-3 0.125
.0001 = 2-4 0.0625
วิธีเปลี่ยนค่าเศษส่วนจากเลขฐานสิบเป็นเศษส่วนขิงเลขฐานสอง ทำได้โดยการคูณค่าเศษส่วนของเลขฐานสิบด้วยค่า 2 ถ้าเกิดการทดค่า 1 หน้าจุดทศนิยม เลขโดด ของตำแหน่งนั้นคือ 1 ถ้าไม่มีการทดค่า เลขโดดของตำแหน่งนั้นคือ 0 ค่าของเศาส่วนของเลขฐานสองจะอ่านจากซ้ายไปขวา
ตัวอย่างที่ 6 จงเปลี่ยนค่า 0.12510 ให้เป็นเลขฐานสอง
0 .125
x 2
0 .250
x 2
0 .500
x 2
1 .000
.0 0 1
ดังนั้น .012510 = 0.0012
ตัวอย่างที่ 7 จงเปลี่ยนค่า 0.562510 ให้เป็นเลขฐานสอง
0 .5625
x 2
1 .1250
x 2
0 .2500
x 2
0 .5000
x 2
1 .0000
.1 0 0 1
ดังนั้น 0.562510 = 0.10012

2.4 การเปลี่ยนค่าเศษส่วนจากเลขฐานสองเป็นเลขฐานสิบ
ค่าเศษส่วนของเลขฐานสิบที่ได้จากการเปลี่ยนค่าจากเลขฐานสองมีค่าเท่ากับผลบวกของเลขโดด 0 หรือ 1 คูณด้วยสองยกกำลัง ตำแหน่งที่ค่าของเลขโดด ของเลขฐานสองในทุกตำแหน่ง
ตัวอย่างที่ 8 จงเปลี่ยนค่า 0.10112 ให้เป็นเลขฐานสิบ
1 0 1 1
= 2-1 + 0 + 2-3 + 2-4
= 0.5 + 0 + 0.125 + 0.0625
= 0.687510

2.5 การบวกและการลบเลขฐานสอง
การบวกเลขฐานสองก็มีวิธีการเช่นเดียวกับการบวกเลขฐานสิบ อาจจะง่ายกว่าการบวกเลขฐานสิบด้วย ตารางการบวกเลขฐานสองมีดังนี้คือ
0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 0 ทดด้วย 1
การทดไปข้างหน้าของเลขฐานสองก็มีวิธีการเช่นเดียวกับเลขฐานสิบในระบบเลขฐานสองค่า 1 เป็นค่ามากที่สุด ดังนั้นเมิ่อมีการบวกได้ค่าที่มากกว่า 1 จึงต้องมีการทดค่าไปข้างหน้า ดังตัวอย่าง
เลขฐานสิบ เลขฐานสอง
5 1 0 1
6 1 1 0
1 1 1 0 1 1
เลขฐานสิบ เลขฐานสอง
1 5 1 1 1 1
2 0 1 0 1 0 0
3 5 1 0 0 0 1 1
ตัวอย่างที่ 9 จงบวกเลขฐานสอง 100101 + 101001
1 0 0 1 0 1
1 0 1 0 0 1
1 0 0 1 1 1 0

ตัวอย่างที่ 10 จงบวกเลขฐานสอง 1101.1 + 1011.1
1 1 0 1.1
1 0 1 1.1
1 1 0 0 1.0
การลบเป็นการดำเนินการที่ผกผันของการบวก ในการลบถ้ามีการลบเลขที่มากกว่าจากเลขที่น้อยกว่า ต้องมีการขอยืมค่าจากเลขที่ถัดไปข้างหน้ามา 1 ตารางแสดงการลบเลขฐานสองมีดังนี้คือ
0 – 0 = 0
1 – 0 = 1
1 - 1 = 0
0 - 1 = 1 ขอยืมมา 1
การขอยืมค่าจากเลขข้างหน้าของเลขฐานสองก็มีวิธีการเช่นเดียวกับเลขซานสิบ ดังตัวอย่าง
เลขฐานสิบ เลขฐานสอง
9 1 0 0 1
5 1 0 1
4 1 0 0
เลขฐานสิบ เลขฐานสอง
1 3 1 1 0 1
6 1 1 0
7 1 1 1
ตัวอย่างที่ 11 จงลบเลขฐานสอง 110011 – 101001
1 1 0 0 1 1
1 0 1 0 0 1
0 0 1 0 1 0
ตัวอย่างที่ 12 จงลบเลขฐานสอง 11101.01 – 1010.10
1 1 1 0 1.0 1
0 1 0 1 0.1 0
1 0 0 1 0.1 1




2.6 การคูณและการหารเลขฐานสอง
การคูณเลขฐานสองมีวิธีการเดียวกับการคูณเลขฐานสิบ มีตารางการคูณดังนี้
0 x 0 = 0
1 x 0 = 0
0 x 1 = 0
1 x 1 = 1
ตัวอย่างที่ 13 จงคูณเลขฐานสอง 1100 x 1010
1 1 0 0
1 0 1 0
0 0 0 0
1 1 0 0
0 0 0 0
1 1 0 0
1 1 1 1 0 0 0
ตัวอย่างที่ 14 จงคูณเลขฐานสอง 1.01 x 10.1
1. 0 1
1 0 .1
1 0 1
0 0 0
1 0 1
1 1 . 0 0 1
การหารเลขฐานสองก็มีวิธีการเช่นเดียวกับการหารเลขฐานสิบ อีกทั้งการหารด้วยเลข 0 นั้นไม่มีความหมาย ตารางแสดงการหารเลขฐานสองมีดังนี้
0 ¸ 1 = 0
1 ¸ 1 = 1
ตัวอย่างที่ 15 จงหารเลขฐานสอง 11001 ¸ 101
1 0 1
101 1 1 0 0 1
1 0 1
1 0 1
1 0 1
2.7 การเปลี่ยนค่าจากเลขฐานสิบเป็นเลขฐานแปดหรือเลขฐานสิบหก
ระบบเลขจำนวนที่ใช้กับคอมพิวเตอร์ นอกจากระบบเลขฐานสองแล้วก็ยังมีระบบเลขฐานแปด และระบบเลขฐานสิบหก ระบบเลขฐานแปดมีเลขโดดอยู่แปดตัวคือ 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 การเปลี่ยนค่าจากเลขฐานสิบเป็นเลขฐานแปด ทำโดยการหารเลขฐานสิบด้วยแปดไปเรื่อยๆ เศษที่ได้จากการหารก็คือค่าของเลขฐานแปด
ตัวอย่างที่ 16 จงเปลี่ยนค่า 20010 ให้เป็นเลขฐานแปด
8 200
25 เศษ 0
3 เศษ 1
0 เศษ 3
ดังนั้น 20010 = 3108ตัวอย่างที่ 17 จงเปลี่ยนค่า 396410 ให้เป็นเลขฐานแปด
8 3964
495 เศษ 4
61 เศษ 7
7 เศษ 5
0 เศษ 7
ดังนั้น 396410 = 75748
การเปลี่ยนค่าจากเลขฐานสิบเป็นเลขฐานสบหก ทำโดยการหารเลขฐานสิบด้วย ค่าสิบหกไปเรื่อยๆ เศษที่ได้จากการหารก็คือค่าของเลขฐานสิบหก แต่เนื่องจากเลขโดดที่ใช้กันมีเพียงสิบตัวเท่านั้น จึงต้องมีการใช้สัญลักษณ์ A-F แทนค่าสิบถึงค่าสิบห้า
ตัวอย่างที่ 18 จงเปลี่ยนค่า 274210 ให้เป็นเลขฐานสิบหก
16 2742
171 เศษ 6
10 เศษ B
0 เศษ A
ดังนั้น 274210 = AB616
ตัวอย่างที่ 19 จงเปลี่ยนค่า 93410 ให้เป็นเลขฐานสิบหก
16 934
58 เศษ 6
3 เศษ A
0 เศษ 3
ดังนั้น 93410 = 3A616
การเปลี่ยนค่าจากเลขฐานแปดให้เป็นเลขฐานสิบ ทำโดยการหาผลบวกของเลขฐานแปดคูณด้วยแปดยกกำลังตำแหน่งของค่านั้น
ตัวอย่างที่ 20 จงเปลี่ยนค่า 3108 ให้เป็นเลขฐานสิบ
3108 = 3x82 + 1x81 + 0x80
= 192 + 8 + 0
= 20010
ตัวอย่างที่ 21 จงเปลี่ยนค่า 75748 ให้เป็นเลขฐานสิบ
75748 = 7x83 + 5x82 + 7x81 + 4x80
= 3584 + 320 + 56 + 4
= 396410
การเปลี่ยนค่าจากเลขฐานสิบหกให้เป็นเลขฐานสิบ ทำโดยการหาผลบวกของเลขฐานสิบหกคูณด้วยสิบหกยกกำลังตำแหน่งของค่านั้น
ตัวอย่างที่ 22 จงเปลี่ยนค่า AB616 ให้เป็นเลขฐานสิบ
AB616 = 10x162 + 11x161 + 6x160
= 2560 + 176 + 6
= 274210
ตัวอย่างที่ 23 จงเปลี่ยนค่า 3A616 ให้เป็นเลขฐานสิบ
3A616 = 3x163 + 10x161 + 6x160
= 768 + 160 + 6
= 93410

2.8 การเปลี่ยนค่าจากเลขฐานสองเป็นเลขฐานแปดหรือเลขฐานสิบหก
ระบบเลขฐานสิบมีเลขโดดสิบตัวคือ 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 และระบบเลขฐานสองมีเลขโดดสองตัวคือ 0 ,1 ดังนั้นระบบเลขฐานแปดก็มีเลขโดดแปดตัวคือ 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 และระบบเลขฐานสิบหกก็จะมีเลขโดดสิบหกตัวคือ 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,A ,B ,C ,D ,E ,F เนื่องจากเลขโดดที่ใช้กันมีเพียงสิบตัวจึงต้องมีการใช้สัญลักษณ์ A-F แทนค่าสิบถึงสิบห้า
ระบบเลขฐานแปดและระบบเลขฐานสิบหกมีประโยชน์ในการพิมพ์โปรแกรม และ memory dump เนื่องจากว่าหน่วยความจำของคอมพิวเตอร์ประเภทมินิคอมพิวเตอร์ และไมโครคอมพิวเตอร์ถูกจัดเป็นกลุ่มเรียกว่า ไบต์ (byte) ซึ่งหนึ่งไบต์ประกอบด้วยเลขฐานสอง 8 ตัว แต่ละไบต์ก็สามารถใช้เป็นสัญลักษณ์แทนตัวอักษรได้หนึ่งตัว หรือว่าจะพิจารณาหนึ่งไบต์เป็นเลขสองกลุ่มๆละ 4 บิต ซึ่งในกรณีหลังนี้กลุ่มของเลขฐานสอง 4 ตัวรวมกันก็คือค่าของเลขฐานสิบหก 1 ตัวนั้นเอง
เลขฐานสิบ เลขฐานสอง เลขฐานแปด เลขฐานสิบหก
0 0 0 0
1 1 1 1
2 10 2 2
3 11 3 3
4 100 4 4
5 101 5 5
6 110 6 6
7 111 7 7
8 1000 10 8
9 1001 11 9
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
จากตารางแสดงค่าของระบบเลข จะเห็นว่าสามารถเปลี่ยนค่าของเลขฐานสองให้เป็นค่าของเลขฐานแปด ได้โดยการจัดกลุ่มของเลขฐานสองทีละสามหลักไปทางซ้ายของจุดทศนิยมสำหรับค่าของจำนวนเต็ม และไปทางขวาของจุดทศนิยมสำหรับค่าเศษส่วน การเปลี่ยนค่าของเลขฐานสองให้เป็นค่าของเลขฐานสิบหก ทำได้โดยการจับกลุ่มของเลขฐานสองทีละสี่หลักไปทางซ้ายของจุดทศนิยมสำหรับค่าจำนวนเต็ม และไปทางขวาของจุดทศนิยมสำหรับค่าเศษส่วน
ตัวอย่างที่ 24 จงเปลี่ยนค่า 10111012 ให้เป็นเลขฐานแปด
1 011 101
1 3 5
10111012 = 1358
ตัวอย่างที่ 25 จงเปลี่ยนค่า 10101.00112 ให้เป็นเลขฐานแปด
1 0101 . 0011
5 1
ในกรณีที่จับกลุ่มแล้วไม่ครบสามหลักให้เติมเลข 0 จนครบสามหลัก มิเช่นนั้นจะผิดไป โดยเฉพาะเลขที่อยู่เลขจุดทศนิยม

0 1 0 1 0 1 0 0 1 1 0 0
2 5 1 4
10101.00112 = 25.148
ตัวอย่างที่ 26 จงเปลี่ยนค่า 110010012 ให้เป็นเลขฐานสิบหก
1100 1001
C 9
110010012 = C916
ตัวอย่างที่ 27 จงเปลี่ยนค่า 110101.10101012 ให้เป็นเลขฐานสิบหก
0 0 1 1 0 1 0 1 . 1 0 1 0 1 0 1 0
3 5 A A
110101.10101012 = 35.AA16

2.9 การเปลี่ยนค่าระหว่างเลขฐานแปดและเลขฐานสิบหก
ระหว่างเลขฐานแปดและเลขฐานสิบหกมีตัวร่วมคือ เลขฐานสอง กล่าวคือ 8 = 23 และ 16 = 24 หรือเลขโดดของฐานแปดแต่ละตัวได้จากการรวมกลุ่มเลขฐานสอง 3 ตัว และเลขโดดของฐานสิบหกแต่ละตัวได้จากการรวมกลุ่มของเลขฐานสอง 4 ตัว ดังนั้นการเปลี่ยน ค่าจากเลขฐานแปดเป็นเลขบานสิบหกทำได้ดดยการเปลี่ยนเลขโดดของเลขบานแปดแต่ละตัวให้เป้นเลขบานสองแล้วจับกลุ่มเลขฐานสองทีละ 4 หลัก ถ้าต้องการเปลี่ยนเลขฐานสิบหกให้เป็นเลขบานแปด ก็ทำได้ดดยการเปลี่ยนเลขโดดของฐานสิบหกแต่ละตัวให้เป้นเลขบานสอง แล้วจับกลุ่มฐานสองทีละ 3 หลัก
ตัวอย่างที่ 28 จงเปลี่ยนค่า 7358 ให้เป้นเลขฐานสิบหก
7 3 5
1 1 1 0 1 1 1 0 1
1 D D
7358 = 1 DD16
ตัวอย่างที่ 29 จงเปลี่ยนค่า A1616 ให้เป็นเลขฐานแปด
A 1 6
1 0 1 0 0 0 0 1 0 1 1 0
5 0 2 6
A1616 = 50268


2.10 2’ Complement
การแสดงของเลขฐานสองที่เป็นค่าบวกเสมอ ( unsigned number ) แต่ละบิตจะมีตัวคูณซึ่งขึ้นอยู่กับตำแหน่งของบิตนั้น เช่น สำหรับเลข 8 บิต
7 6 5 4 3 2 1 0 ตำแหน่งที่

27 26 25 24 23 22 21 20 ค่ากำลังสองของตำแหน่ง
128 64 32 16 8 4 2 1 ค่าเลขฐานสิบ
ในการประมวลผลข้อมูลด้วยคอมพิวเตอร์ ข้อมูลที่ใช้ในการประมวลผลมีทั้งข้อมูลที่เป็นบวกและลบ ( signed number ) ดังนั้นการแสดงค่าของเลขฐานสองก็ต้องสามารถแสดงค่าได้ทั้งค่าบวกและค่าลบ เมื่อ 1 ไบต์เก็บค่าของตัวเลข เลข 7 บิตทางขวาจะแสดงค่า และบิตที่ 8 แสดงเครื่องหมายบวกหรือลบ คือถ้าบิตที่ 8 มีค่าเป็น 0 แสดงว่าค่านั้นเป็นบวก ถ้าบิตที่ 8 มีค่าเป็น 1 แสดงว่าค่านั้นเป้นลบ
ดังนั้น 1 ไบต์ สามารถแสดงค่าบวกระหว่าง 0 ( 00000000 ) ถึง 127 ( 01111111 ) และค่าลบระหว่าง -1 ( 11111111 ) ถึง 128 ( 10000000 )
7 6 5 4 3 2 1 0
Unsigned number

DATA

7 6 5 4 3 2 1 0
Positive signed number

DATA

7 6 5 4 3 2 1 0
Negative signed number

DATA
การหาค่าของเลขฐานสองที่เป็นค่าลบทำได้โดย
1. หาค่าของเลขบานสองที่เป็นค่าบวก
2. หาค่า 1s complement โดยการเปลี่ยนค่าของแต่ละบิต จาก 0 เป็น 1 และจาก 1 เป็น 0
3. บวกค่า 1 กับค่าที่ได้ในข้อ 2
ตัวอย่างที่ 30 จงเปลี่ยนค่า -12 ให้เป็นเลขฐานสอง
1. หาค่าเลขฐานสองของ 12
2 12
6 เศษ 0
3 เศษ 0
1 เศษ 1
0 เศษ 1
1210 = 11002
2. หาค่า 1s complement โดยการสลับค่าของแต่ละบิต
1100
สลับบิตได้ 0011
3. บวกค่า 1 กับค่าที่ได้ในข้อ 2
0 0 1 1
1
0 1 0 0


















แบบฝึกหัด
1. จงเติมตัวเลขให้สมบูรณ์

เลขฐานสอง
เลขฐานสิบ
เลขฐานสิบหก

4091


0.375


131.5625

11011


0.1011


1110.1001


10110.1011


100100


101.011



75


-35


125


-107


20



2B


3E


122


0E








2.จงหาผลลัพธ์ต่อไปนี้

เลขฐานสอง
ผลลัพธ์
1001.1 + 1011.01

0.1101 + 0.1011

1010 + 1111

1100.011 + 1011.011

1101 - 1000

1011.1 - 101.1

1101.1 - 1011.1

111.11 - 1010.01

1011101.1 - 101010.11

1011110.1 - 101011.11

1111 x 1101

1010 x 1111

111.11 x 10.1

10110.1 x 100.11

10010 x 1110

101100 ¸ 1011

101010 ¸ 1100

11111.1 ¸ 1111.11

11011 ¸ 10010










3.จงเขียนเลข 10 ค่าแรกของระบบเลขฐานสี่ ซึ่งมีเลขโดดอยู่ 4 ตัวคือ 0 ,1 ,2 ,3
ตอบ



4.จงเขียนเลข 20 ค่าแรกของระบบฐานสิบสอง ซึ่งมีเลขโดดอยู่ 12 ตัวคือ
0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 , A,B
ตอบ



5.จงเปลี่ยนค่าต่อไปนี้ให้เป็น 2’s complement

เลขฐานสอง
2’s complement
1011

11011

1101

1010

1111

1110

110111

100100

10011










เฉลย
1.
เลขฐานสอง
เลขฐานสิบ
เลขฐานสิบหก
11111111001
4091
7F9
0.011
0.375
0.6
10000011.1001
131.5625
83.9
11011
27
1B
0.1011
0.6875
0.B
1110.1001
14.5625
E.9
10110.1011
22.6875
16.B
100100
36
24
101.011
5.375
5.6
0100-1011
75
4B
1101-1101
-35
DD
0111-1101
125
7D
1001-0101
-107
95
0010-1000
20
28
43
0010-1011
2B
62
0011-1110
3E
290
0001-0010-0010
122
14
0000-1110
0E








2.

เลขฐานสอง
ผลลัพธ์
1001.1 + 1011.01
10100.11
0.1101 + 0.1011
1.1000
1010 + 1111
11001
1100.011 + 1011.011
10111.110
1101 - 1000
0101
1011.1 - 101.1
110.0
1101.01 - 1011.1
0000.11
111.11 - 1010.01
010.01
1011101.1 - 101010.11
110010.11
1011110.1 - 101011.11
110010.11
1111 x 1101
11000011
1010 x 1111
10010110
111.11 x 10.1
10011.011
10110.1 x 100.11
1101010.111
10010 x 1110
11111100
101100 ¸ 1011
100
101010 ¸ 1100
11.1
11111.1 ¸ 1111.11
100
11011 ¸ 10010
1.1

3. ตอบ 0 ,1 ,2 ,3 ,10 ,11 ,12 ,13 ,20 ,21
4. ตอบ 0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,A ,B ,10, 11 ,12 ,13 ,14 ,15 ,16 ,17 ,18





5.
เลขฐานสอง
2’s complement
1011
1001
11011
00011011
1101
10101011
1010
11010011010
1111
101000010100
1110
10010.1011
110111
11001101
100100
10101010.00011010
10011
101010110010.001000110100

MICROPROCESSER

ไมโครโปรเซสเซอร์ เก่าสุดๆ
Microprocessor นั้นมีหลายชนิดตามแต่บริษัทจะผลิตขึ้นมา เช่น Microprocessor ที่ผลิตโดยบริษัท Intel ซึ่งเป็นตระกูล x86 ซึ่งในปัจจุบันเป็นรุ่น Pentium นอกจากนี้ยังมี Microprocessor ที่ผลิตขึ้นโดยบริษัทอื่นๆอีก เช่น ตระกูล 68000 และ PowerPC ซึ่งเป็นของบริษัท Motorola ตระกูล Alpha ของบริษัท DEC และตระกูล Sparc ของบริษัท Sun Microsystem เป็นต้น โดย Microprocessor แต่ละตัวนี้จะมีชุดของคำสั่งที่ไม่เหมือนกันจึงทำให้ภาษา Assembly นี้ไม่สามารถนำไปใช้บนเครื่องต่างชนิดกันได้ ดังนั้นในรายงานฉบับนี้จึงขอนำเสนอภาษา Assembly ที่ใช้กับเครื่องตระกูล x86 ซึ่งเป็นของบริษัท Intel ส่วนภาษา Assembly สำหรับเครื่องตระกูล PowerPC
รายละเอียดของ Microprocessor รุ่นต่างๆในตระกูล x86 เป็นดังนี้
1. ไมโครโพรเซสเซอร์ 4004 (1971) เป็นชิพ CPU ตัวแรกของบริษัท Intel ซึ่งเป็น Microprocessor ขนาด 4 บิต มีหน่วยความจำที่เก็บโปรแกรมและข้อมูลแยกกันต่างหาก มันทำงานที่ความเร็วของสัญญาณนาฬิกาเท่ากับ 740 kHz มีคำสั่งภาษาเครื่องอยู่ 46 คำสั่ง
2. ไมโครโพรเซสเซอร์ 4040 (1972) ได้ถูกพัฒนาต่อมาจาก 4004 ยังคงเป็น Microprocessor ขนาด 4 บิต แต่ว่าได้มีการเพิ่มคำสั่งภาษาเครื่องเข้ามาจากเดิมอีก 14 คำสั่ง
3. ไมโครโพรเซสเซอร์ 8008 (1972) ถูกพัฒนาให้กลายเป็น Microprocessor ขนาด 8 บิต ทำให้สามารถประมวลผลข้อมูลได้เป็น 2 เท่าของเครื่อง 4004 และ 4040
4. ไมโครโพรเซสเซอร์ 8080 (1974) 8080 นี้ได้ถูกพัฒนาให้มีความเร็วในการทำงานมากกว่า 4004 ถึง 20 เท่า แต่ว่าก็ยังคงเป็น Microprocessor ขนาด 8 บิตเหมือนเดิม
5. ไมโครโพรเซสเซอร์ 8088/8086
คอมพิวเตอร์ IBM PC รุ่นแรกจะเป็นคอมพิวเตอร์แบบ 16 บิต โดยใช้ CPU ที่เป็นไมโครโพรเซสเซอร์เบอร์ 8088 เรียกคอมพิวเตอร์รุ่นนี้ว่ารุ่น XT หรือ PC/XT ส่วนประกอบภายในจะกระทำกับข้อมูลขนาด 16 บิต จำนวน 14 ตัว โดยการประมวลผลภายในจะกระทำกับข้อมูลขนาด 16 บิต แต่การติดต่อกับอุปกรณ์ภายนอก CPU จะใช้บัสข้อมูล ขนาด 8 บิต CPU รุ่นนี้จะมีสายแอดเดรสทั้งหมด 20 เส้นทำให้อ้างตำแหน่งได้ 1 MB สำหรับ CPU รุ่น 8086 โครงสร้างภายในจะเหมือนกับรุ่น 8088 แต่จะติดต่อกับอุปกรณ์ภายนอกด้วยบัสข้อมูลแบบ 16 บิต จึงเรียกรุ่น 8086 ว่าเป็น 16 บิตที่แท้จริง
6. ไมโครโพรเซสเซอร์ 80286
ไมโครโพรเซสเซอร์รุ่นนี้เรียกสั้น ๆ ว่า 286 เป็นรุ่นที่พัฒนาต่อจาก 8086 มีประสิทธิภาพสูงมากใช้ในเครื่อง คอมพิวเตอร์ IBM PC/AT บัสข้อมูลของไมโครโพรเซสเซอร์รุ่นนี้เป็นแบบ 16 บิต แต่มีแอดเดรสบัส 24 เส้นทำให้อ้างตำแหน่งของ ข้อมูลได้มาก ขึ้นการทำงานของ 286 จะมีสองแบบคือแบบเรียลโหมด และแบบโปรเทคต์โหมด โดย แบบเรียลโหมดการทำงานจะเหมือนกับ 8086 อ้างหน่วยความจำได้ 1MB แต่แบบโปรเทคต์โหมดจะติดต่อกับ หน่วยความจำได้มากที่สุดเท่าที่มีหน่วยความจำต่ออยู่ แต่ ไม่เกิน 16 MB การทำงานของไมโครโพรเซสเซอร์รุ่นนี้ สามารถ ทำงานหลายโปรแกรมในเวลาเดียวกันได้ เรียกการทำงานแบบ นี้ว่า มัลติทาสกิ่ง นอกจากนี้ 286 ยังทำงานท ี่ความถี่สัญญาณที่สูงขึ้น ทำให้ CPU ทำงานได้เร็วมากขึ้น
7. ไมโครโพรเซสเซอร์ 80386
เป็นรุ่นที่พัฒนาจากรุ่น 286 ให้ทำงานได้ดีขึ้นใช้สัญญาณนาฬิกาที่มีความถี่สูงขึ้น รีจิสเตอร์เป็นแบบ 32 บิต ดังนั้น การโอนย้าย ข้อมูลจะเป็นแบบ 32 บิตสามารถอ้างหน่วยความจำได้สูงถึง 4000 MB สามารถอ้างหน่วยความจำ ได้ทั้งแบบเรียลโหมด และแบบโปรเทคต์โหมด ไมโครโพรเซสเซอร์รุ่นได้ออกมาสองรุ่นคือ 80386DX และ 80386SX โดย 80386DX จะใช้บัส ข้อมูลขนาด 32 บิต บัสแอดเดรสขนาด 32 บิต ส่วน 80386SX ใช้บัสข้อมูล ภายนอกขนาด 16 บิต และใช้แอดเดรสบัสขนาด 24 บิต
8. ไมโครโพรเซสเซอร์ 80486
เป็นรุ่นที่พัฒนาต่อจากรุ่น 386 โดยใช้สัญญาณนาฬิกาที่เร็วกว่าและมีหน่วยความจำแคชประกอบอยู่ภายใน ไมโครโพรเซสเซอร์รุ่น ได้ออกมาหลายรุ่นคือ 486DX เป็นรุ่นที่มีหน่วยประมวลผลร่วมทางคณิตศาสตร์ประกอบ อยู่ภายใน รุ่น 486SX เป็นรุ่นที่มีราคา ถูกลงโดยตัดหน่วยประมวลผลร่วมทางคณิตศาสตร์ออกไป รุ่น 486DX2 และ DX4 เป็นรุ่นที่พัฒนาให้ทำงานได้เร็วขึ้นเรียกว่า Overdrive Processor โดยจะเพิ่มความถี่ของสัญญาณนาฬิกาภายใน จากสัญญาณนาฬิกาภายนอก 2 และ 3 เท่าตามลำดับสำหรับ หน่วยความจำแคชเป็นหน่วยความจำที่ทำให้ คอมพิวเตอร์ทำงานได้เร็วขึ้นถ้าหาก CPU ทำงานร่วมกับหน่วยความจำทั่วไปบางครั้ง CPU ทำงานได้เร็วกว่า เวลาที่หน่วยความจำทำงาน ทำให้ CPU ต้องหยุดรอในการอ่านเขียนข้อมูกับหน่วยความจำ จึงมีการ นำหน่วยความจำ แคชมาใช้ โดยแคชเป็นหน่วยความจำประเภทหนึ่งที่ทำงานได้เร็วมาก และจะมีตัวควบคุมแคช ทำหน้าที่เก็บ ข้อมูลที่ CPU ต้องการใช้บ่อย ๆ เอาไว้ เมื่อ CPU ทำงาน CPU จะหาข้อมูลในแคชก่อนถ้าไม่มีข้อมูลที่ต้องการ CPU จะไปหา ข้อมูลในหน่วยความจำ RAM ซึ่งทำงานช้ากว่าหน่วยความจำแคช
9. ไมโครโพรเซสเซอร์เพนเทียม
เป็นไมโครโพรเซสเซอร์ที่ถูกพัฒนาให้มีประสิทธิภาพสูงขึ้น บัสข้อมูลในการติดต่อกับอุปกรณ์ภายนอกเป็นแบบ 64 บิต สามารถอ้างหน่วยความจำได้มากขึ้น มีหน่วยความจำแคชภายในขนาดใหญ่ขึ้นในไมโครโพรเซสเซอร์จะ ทำงาน ออกเป็นสองส่วน คือ Execute Unit (EU) และ Bus Interface Unit (BIU) ดังรูป การทำงานของ EU จะทำหน้าที่ ประมวลผล รหัสคำสั่งและข้อมูลที่ได้รับมาจาก BIU การเปลี่ยนแปลงหรือการกระทำกับข้อมูลใด ๆ จะต้องเกิดจากส่วย EU จะประกอบ ด้วยรีจิสเตอร์ที่ใช้งานทั่วไปได้แก่ AX, BX, CX, DX สแตกพอยน์เตอร์ (SP) เบสพอยน์เตอร์ (BP) ซอร์สอินเด็กซ์ (SI) เดสทิเนชันอินเด็กซ์ (DI) รีจีสเตอร์แฟลก หน่วยควบคุม รวมทั้งหน่วยประมวลผลทางคณิตศาสตร์และลอจิกที่เรียกว่า ALU ส่วน BIU จะทำหน้าที่เชื่อมต่อบัสในการส่งข้อมูล ต่าง ๆ ควบคุมการเข้าถึงหน่วยความจำและการติดต่อกับอุปกรณ์ภายนอกต่าง ๆ ของตัวไมโครโพรเซสเซอร์ ประกอบด้วย หน่วยควบคุมบัส รีจิสเตอร์เซกเมนต์ วงจรลอจิกที่ใช้อ้างตำแหน่งหน่วยความจำ เป็นต้น ในโพรเซส เซอร์โมเดลเราจะเห็นว่าประกอบด้วยรีจิสเตอร์ต่าง ๆ มากมาย โดยรีจิสเตอร์หมายถึงหน่วยเก็บข้อมูลชั่วคราว ที่มีหน้าท ี่เฉพาะภายในไมโครโพรเซสเซอร์
การให้คอมพิวเตอร์ทำงานคือการให้ไมโครโพรเซสเซอร์ทำงานโดยจะเริ่มจากการอ่านข้อมูลจากหน่วยความจำ โปรแกรมเข้ามาในตัวไมโครโพรเซส เซอร์จากนั้น จะถอด รหัสคำสั่งและทำงานตามคำสั่งเมื่อทำงานตาม

รีจิสเตอร์ (Register)

รีจิสเตอร์เป็นส่วนประกอบส่วนหนึ่งของไมโครโพรเซสเซอร์ที่ทำหน้าที่เก็บข้อมูลชั่วคราวภายใน CPU สำหรับเตรียมการประมวลผลต่างๆดังที่กล่าวมาแล้ว โดยรีจิสเตอร์ภายใน CPU นั้นมีหลายตัว สามารถแบ่งเป็นกลุ่มๆ ได้ดังนี้
Þ รีจิสเตอร์ใช้งานทั่วไป ( General Purpose Register )
Þ รีจิสเตอร์ตัวชี้และอินเด็กซ์ ( Pointer & Index Register )
Þ รีจิสเตอร์เซกเมนต์ ( Segment Register )
Þ รีจิสเตอร์แฟลก ( Flag Register )

รีจิสเตอร์ใช้งานทั่วไป ( Gerneral Purpose Register )
กลุ่มรีจิสเตอร์ใช้งานทั่วไปหรือกลุ่มรีจิสเตอร์ข้อมูลประกอบด้วยรีจิสเตอร์ AX หรือ Accumulator และรีจิสเตอร์ BX,CX และ DX ซึ่งเป็นรีจิสเตอร์ขนาด 16 บิต ( ถ้าเป็นไมโครโพรเซสเซอร์รุ่น 80386 จะเป็น 32 บิต โดยมีตัว E นำหน้า เช่น EAX ) รีจิสเตอร์เหล่านี้จะแบ่งเป็นรีจิสเตอร์ขนาด 8 บิต 2 ตัวได้ อย่างเช่นรีจิสเตอร์ AX แบ่งเป็น 8 บิตต่ำคือ AL และ 8 บิตสูงคือ AH รีจิสเตอร์เหล่านี้สามารถใช้เก็บข้อมูลทั่วไปได้ แต่โดยทั่วไปแล้วรีจิสเตอร์ AX จะใช้เก็บข้อมูลที่จะนำไปประมวลผลและเก็บค่าผลลัพธ์จากการประมวลผล เช่นการ บวก ลบ คูณ หาร ภายใน CPU โดยรีจิสเตอร์ AX ยังทำงานกับอุกรณ์อินพุต เอาท์พุตได้อีกด้วย รีจิสเตอร์ BX ( Base register ) ใช้เป็นรีจิสเตอร์ชี้ฐานข้อมูลในการประมวลผลแบบตาราง รีจิสเตอร์ CX ( Count Register ) ใช้เป็นตัวนับในการให้โปรแกรมทำงานแบบซ้ำๆหรือแบบลูป โดยคำสั่งต่างๆ ของไมโครโพรเซสเซอร์ที่ทำงานเกี่ยวกับการนับ การหมุนข้อมูล การเลื่อนข้อมูล จะใช้รีจิสเตอร์ตัวนี้ด้วย รีจิสเตอร์ DX ( Data Register ) ใช้ในการเก็บข้อมูลเพื่อทำการคูณ หารเลขและใช้ในากรอ้สางตำแหน่งข้อมูลโดยอ้อมในการเขียนโปรแกรม
รีจิสเตอร์ขนาด 16 บิตทั้ง 4 ตัว สามารถแยกออกเป็นรีจิสเตอร์ 8 บิตได้ โดย AX แยกออกเป็น AH และ AL รีจิสเตอร์ BH และBL แยกออกจากรีจิสเตอร์ BX เป็นต้น
ดังรูป

AX BX

AH AL BH BL


CX DX
CH CL DH DL


รูป ลักษณะของรีจิสเตอร์



เราสามารถเขียนคำสั่งย้ายข้อมูลต่างๆกับรีจิสเตอร์ได้ เช่น MOV AL,BH ,
MOV DL,CL หรืออาจเป็นคำสั่งบวกเช่น ADD BL,DH รีจิสเตอร์ขนาด 8 บิต จะนำไปกระทำกับรจิสเตอร์ 16 บิตไม่ได้ เช่น MOV DL,DH จะทำงานไม่ได้
รีจิสเตอร์ตัวชี้และอินเด็กซ์ ( Pointer & Index Register )
ในไมโครโพรเซสเวอร์ 8086 รีจิสเตอร์กลุ่มนี้จะเป็น 16 บิตทั้งหมด ไม่สามารถแบ่งเป็น 8 บิตต่ำและ 8 บิตสูงได้ รีจิสเตอร์กลุ่มนี้ใช้ในการชี้ตำแหน่งหน่วยความจำที่ต้องการติดต่อ ประกอบด้วยรีจิสเตอร์ SP,BP,SI และ DI รีจิสเตอร์แต่ละตัวมีหน้าที่เฉพาะอย่างดังต่อไปนี้
SP ( Stack Pointer ) ใช้ตำแหน่งหน่วยความจำที่เป็นแสตกโดยใช้ร่วมกับรีจิสเตอร์ SS
BP ( Base Pointer ) ใช้ชี้ตำแหน่งของข้อมูลคล้ายกับรีจิสเตอร์ SP แต่จะชี้ตำแหน่งของข้อมูลทั่วไป
SI ( Source Index ) ใช้ร่วมกับรีจิสเตอร์ DS ใช้ชี้ตำแหน่งของหน่วยความจำข้อมูล
DI ( Destination Index ) คล้ายกับรีจิสเตอร์ SI แต่จะทำงานเกี่ยวกับสตริงและทำงานร่วมกับรีจิสเตอร์ ES
รีจิสเตอร์เซกเมนต์ ( Segment Registers)
กลุ่มเซกเมนต์เป็นรีจิสเตอร์ในส่วนของ BIU ที่ใช้ในการอ้างตำแหน่งหน่วยความจำเมื่อต้องการอ่านเขียนข้อมูล โดยจะแบ่งหน่วยความจำออกเป็นเซกเมนต์ รีจิสเตอร์แต่ละตัวมีหน้าที่ดังนี้
รีจิสเตอร์ CS ใช้เก็บค่าเซกเมนต์แอดเดรสเอาไว้หรือตำแหน่งของโปรแกรมใน Code Segment โดยจะทำงานร่วมกับรีจิสเตอร์ชี้คำสั่ง IP ซึ่งเป็นค่า Offset ในการชี้ตำแหน่งคำสั่งโปรแกรม
รีจิสเตอร์ DS ใช้เก็บค่าตำแหน่งเซกเมนต์ส่วนที่เป็นข้อมูล หรือ Data Segment ดดยทั่วไปจะใช้ในการอ้างแอดเดรสที่เก็บข้อมูลสตริง ข้อมูลที่อยู่ใน DS จะถูกนำมาบวกกับค่าออฟเซตเพื่ออ้างตำแหน่งหน่วยความจำที่ต้องการติดต่อ
รีจิสเตอร์ SS ใช้เก็บตำแหน่งเซกเมนต์ส่วนที่เป็นหน่วยความจำแสตกหรือ Stack Segment โดยจะทำงานร่วมกับรีจิสเตอร์ SP หรือตัวชี้แสตก
รีจิสเตอร์ ES ใช้ชี้แอดเดรสหน่วยความจำที่เป็น Extra Segment โดยใช้ร่วมกับรีจิสเตอร์ DI
รีจิสเตอร์คำสั่ง ( Instruction Pointer )
รีจิสเตอร์ Instruction Pointer ( IP ) หรือรีจิสเตอร์คำสั่ง จะทำงานร่วมกับรีจิสเตอร์ CS โดยใช้เก็บตำแหน่งคำสั่งถัดไปที่จะให้ไมโครโพรเซสเซอร์ทำงาน
รีจิสเตอร์แฟลก ( Flags Register )
รีจิสเตอร์จะใช้เก็บสถานะต่างๆจากการประมวลผลของไมโครโพรเซสเซอร์ เมื่อไมโครโพรเซสเซอร์ทำคำสั่งบางคำสั่ง ผลลัพธ์ที่ได้อาจมีผลต่อแฟลกเพื่อบอกสถานะของผลลัพธืที่ได้ รีจิสเตอร์แฟลกแบ่งเป็น 2 ส่วนคือ แฟลกสถานะ ( Status Flags ) และแฟลกควบคุม ( Control Flags ) โดยรีจิสเตอร์แฟลกนี้ค่าบิตต่างๆจะมีความหมายเฉพาะดังรูป


15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
OF DF IF TF SF ZF AF PF CF

รูป บิตต่างๆในรีจิสเตอร์แฟลก
Þ OF ( Overflow ) เป็นบิตที่บอกว่าผลลัพธ์จากการคำนวณมีค่าเกินกว่าที่รีจิสเตอร์จะเก็บได้
Þ DF ( Direction ) เป็นบิตที่กำหนดทิศทางการเคลื่อนที่ของข้อมูลสตริงว่าจะให้เคลื่อนที่จากซ้ายไปขวาหรือขวาไปซ้าย
Þ IF ( Interrupt ) เป็นบิตกำหนดให้ยอมรับการอินเทอร์รัพต์จากภายนอก ถ้าเป็น 1หมายความว่า CPU จะถูกอินเทอร์รัพต์จากภายนอกได้ แต่ถ้าเป็น 0 หมายความว่า CPU จะถูกอินเทอร์รัพต์จากภายนอกไม่ได้
Þ TF ( Trap ) เป็นบิตที่บอกให้ไมโครโพรเซสเซอร์ทำงานทีละคำสั่ง ถ้าบิตนี้ถูกเซตเป็น 1 CPU จะทำงานแบบซิงเกิลสเตป ( Single Step ) ซึ่งทำให้เราสามารถดูผลการทำงานทีละคำสั่งได้
Þ SF ( Sign ) เป็นบิตแสดงเครื่องหมายผลลลัพต์ที่ได้จากการทำงานทางคณิตศาสตร์ ถ้าเป็น 0 หมายความว่าเป็นเลขบวก ถ้าเป็น 1 แสดงว่าเป็นเลขลบ
Þ ZF ( Zero ) เป็นบิตแสดงผลลัพธ์จากการคำนวณทางคณิตศาสตร์ว่ามีค่าเป็น 0 หรือไม่ ถ้าบิตนี้เซตเป็น 1 หมายความว่าข้อมูลที่ได้เป็น 0
Þ AF ( Auxiliary ) เป็นบิตที่ช่วยคิดดการคำนวณแบบ BCD โดยจะเป็นตัวช่วยทดถ้ามีการทดจากบิต 3 ไป 4
Þ PF ( Parity ) เป็นบิตบอกพาริตี้ข้อมูลว่ามีจำนวนบิตที่เป็นลอจิก 1 เป็นคู่หรือคี่
Þ CF ( Carry ) เป็นบิตแฟลกตัวทดที่เก็บข้อมูลการทดจากการทดบิตสูงสุดการคำนวณทางคณิตศาสตร์ ถ้ามีการทดหรือการยืมเกิดขึ้นบิตนี้จะถูกเซ็ตเป็นลอจิก 1


เซกเมนต์หน่วยความจำ

การจัดหน่วยความจำที่นิยมใช้มีอยู่ 2 ประเภทโดยไมโครโพรเซสเซอร์ของโมโตโลราจะอ้างตำแหน่งหน่วยความจำแบบ Linear addressing ส่วนไมโครโพรเซสเซอร์ของอินเทลตระกูล 80*86 จะอ้างหน่วยความจำแบบ segment addressing
รีจิสเตอร์ CS,DS,SS และ ES เป็นรีจิสเตอร์เซกเมนต์ใช้ชี้ตำแหน่งหน่วยความจำที่เก็บรหัสคำสั่งและข้อมูลทำให้ไมโครโพรเซสเซอร์สามารถเข้าถึงตำแหน่งหน่วยความจำได้
เนื่องจากขนาดของข้อมูลที่เก็บในหน่วยความจำมีขาดเป็นไบต์โพรเซสเซอร์ 8086 มีขาแอดเดรสจำนวน 20 บิต ดังนั้น จะอ้างตำแหน่งหน่วยความจำได้ 220 หรือ 1,048,576 หรือ 1 เมกกะไบต์ ตำแหน่งนี้เรียกว่า physical address ค่าแอดเดรส 5 ตำแหน่งแรกค่าของบิตต่างๆ ในแอดเดรสบัสจะเป็นดังนี้
0000 0000 0000 0000 0000
0000 0000 0000 0000 0001
0000 0000 0000 0000 0010
0000 0000 0000 0000 0011
0000 0000 0000 0000 0100
แต่การเขียนค่าแอดเดรสเป็นเลขไบนารีจะยาวจึงนิยมเขียนเป็นเลขฐาน 16 ห้าหลัก ดังต่อไปนี้

00000H
00001H
00002H
………
00009H
0000AH
ค่าตำแหน่งแอดเดรสสูงสุดที่โพรเซสเซอร์ 8086 อ้างได้คือ FFFFFH
ในการอ้างตำแหน่งหน่วยความจำจะใช้รีจิสเตอร์เซกเมนต์เป็นตัวชี้ตำแหน่ง โดยรีจิสเตอร์ CS ใช้ชี้เซกเมนต์หน่วยความจำที่เก็บรหัสคำสั่ง รีจิสเตอร์ DS ใช้ชี้เซกเมนต์หน่วยความจำที่เก็บข้อมูล รีจิสเตอร์ SS ใช้ชี้หน่วยความจำที่เป็นสแตก
ไมโครโพรเซสเซอร์ 8086 ขนาดของแอดเดรสบัสมีขนาด 20 บิต ดังนั้นจะอ้างตำแหน่งได้ 1,048,576 ตำแหน่ง ในรูป 1.9 จะแสดงตำแหน่งหน่วยความจำจะเห็นว่าสามารถเก็บเวิร์ดข้อมูลขนาด 16 บิต ได้จำนวน 524,288 เวิร์ด โดย 1 เวิร์ดมีขนาดเท่ากับ 2 ไบต์
เนื่องจากไมโครโพรเซสเซอร์ 8086 มีขาแอดเดรส 20 เส้น แต่รีจิสเตอร์ที่เก็บตำแหน่งของหน่วยความจำมีขนาด 16 บิต จึงมีการแบ่งหน่วยความจำออกเป็นบล็อกๆ เรียกว่าเซกเมนต์หน่วยความจำ ( Memory Segment ) โดยหนึ่งเซกเมนต์มีขนาด 216 หรือ 64K เซกเมนต์แต่ละเซกเมนต์กำหนดด้วยตัวเลขเซกเมนต์ ( Segment Number ) ซึ่งมีข้อมูขขนาด 16 บิต ค่าตัวเลขเซกเมนต์สูงสุด คือ 0FFFFH


ไบต์ 1,048,575
ไบต์ 1,048,574



ไบต์ 3
ไบต์ 2
ไบต์ 1
ไบต์ 0

รูป แสดงหน่วยความจำที่เก็บข้อมูลไบต์ขนาด 16 บิต
เมื่อมีการกำหนดตำแหน่งหน่วยความจำเป็นเซกเมนต์ การเข้าถึงหน่วยความจำต้องระบุว่าเป็นค่าตำแหน่งใดในเซกเมนต์นั้นๆ ค่านี้เรียกว่าค่าออฟเซต ( Offset Addressing ) คล้ายกับการมองหน่วยความจำเป็นตึกหนึ่งหลังโดยแต่ละห้องจะแทนตำแหน่งไบต์ข้อมูล ค่าเซกเมนต์จะแทนด้วยหมายเลขชั้นของตึก ส่วนตำแหน่งห้องในแต่ละชั้นจะแทนด้วยค่าออฟเซต โดยการบอกตำแหน่งห้องจะต้องบอกว่าอยู่ชั้นใด ห้องลำดับที่เท่าไร ดังนั้นในการบอกตำแหน่งหน่วยความจำที่ต้องการติดต่อจะต้องบอกทั้งเลขเซกเมนต์และค่าออฟเซตแอดเดรส ซึ่งมีรูปแบบเป็น
<> : <>
ค่าแอดเดรสแบบนี้เรียกว่า logical address ถ้าหากไมโครโพรเซสเซอร์ตัวที่กำลังศึกษาอยู่มีรีจิสเตอร์ที่เป็นตัวชี้เซกเมนต์ขนาด 16 บิต และรีจิสเตอร์ขนาดที่เป็นค่าออฟเซตขนาด 16 บิต ด้วยแอดเดรสของหน่วยความจำเริ่มต้นในแต่ละเวกเมนต์จะมีค่าออฟเซตเป็น 0000H และแอดเดรสสุดท้ายในเซกเมนต์นั้นจะมีค่าออฟเซตเป็น FFFFH ดังรูป



หน่วยความจำตำแหน่งต่างๆ


ตำแหน่งเริ่มต้นเซกเมนต์ ค่าออฟเซตเป็น 0000


รูป ตัวอย่างเซกเมนต์หน่วยความจำ
ตัวอย่างเช่นถ้าบอกค่าแอดเดรสเป็น A4FB:4872H หมายความว่าค่าออฟเซตเป็น 4872H ในเซกเมนต์ A4FBH สำหรับไมโครโพรเซสเซอร์ 8086 จะคำนวณค่า logic address เป็นข้อมูล 20 บิต หรือ physical address ได้โดยเลื่อนค่าเซกเมนต์แอดเดรสออกไป 4 บิต ซึ่งทำได้โดยเลื่อนฐาน 16 ออกไปหนึ่งหลักและบวกด้วยค่าออฟเซต ดังนั้นค่า physical address ของ A4FB : 4872 คือ
A4FB0H
+ 4872H
A9822H ( 20 บิต physical address )
การแบ่งหน่วยความจำออกเป็นเซกเมนต์นั้นเซกเมนต์แรกจะเป็นเซกเมนต์ที่ 0 โดยเริ่มที่ตำแหน่ง 0000 : 0000 = 00000H สิ้นสุดที่ตำแหน่ง 0000 : FFFF = 0FFFFH ต่อไปจะเป็นเซกเมนต์ที่ 1 เริ่มที่ตำแหน่ง 0001 : 0000 = 00010H และสิ้นสุดเซกเมนต์ที่ตำแหน่ง 0001 : FFFF = 1000FH จะเห็นว่าแต่ละเซกเมนต์จะมีตำแหน่งที่เหลื่อมซ้อนกันอยู่
ในไมโครโพรเซสเซอร์เบอร์ 8086 การเขียนโปรแกรมจะต้องกำหนดเซกเมนต์ต่างๆ ของหน่วยความจำ สำหรับเก็บโปรแกรมและเก็บข้อมูลต่างๆ ดังรูป การจัดเซกเมนต์หน่วยความจำ

FFFFF

Data EFFFF
Segment
E0000
Code segment ( CS )
B 3 F F Code
Segment C3FEF

Data segment ( DS ) B3FF0
E 0 0 0

Stack segment ( SS ) 6D26F
5 D 2 7


Extra segment ( ES )
5 2 B 9 0000






ถึงตรงนี้เราอาจมองว่าในการอ้างตำแหน่งต่างๆของหน่วยความจำในโหมดจริง จะต้องใช้รีจิสเตอร์ 2 ตัวเป็นตัวชี้ โดยรีจิสเตอร์ตัวหนึ่งเป็นค่าเซกเมนต์ โดยรีจิสเตอร์อีกตัวเป็นค่าออฟเซต ตัวอย่างเช่นการชี้ตำแหน่งความจำที่เก็บคำสั่งจะต้องใช้รีจิสเตอร์ 2 ตัว คือ รีจิสเตอร์ CS เป็นตัวชี้ segment รีจิสเตอร์ IP เป็นค่าออฟเซต และไมโครโพรเซสเซอร์จะนำรีจิสเตอร์ 2 ตัวมาคำนวณเป็นค่าแอดเดรสจริงได้
ดังรูป

16 บิต

CS A 0 0 0

+ 16 บิต
IP 5 F 0 0


20 บิต
A 5 F 0 0

รูป การนำรีจิสเตอร์ 2 ตัวมาชี้ตำแหน่งหน่วยความจำ


โครงสร้างของคอมพิวเตอร์ PC


ระบบคอมพิวเตอร์จะประกอบด้วยส่วนที่เป็นฮาร์ดแวร์(hardeare) ซอฟต์แวร์ (solftware) โดยซอฟต์แวร์หรือโปรแกรมจะทำหน้าที่ควบคุมต่างๆ ตามที่ต้องการ
การทำงานของคอมพิวเตอร์นั้นจะถูกควบคุมด้วยโปรแกรม และเนื่องจากคอมพิวเตอร์เป็นอุปกรณ์ที่ทำงานได้หลายอย่างซึ่งการทำงานแต่ล่ะอย่างจะต้องใช้โปรแกรมที่แตกต่างกัน ดังนั้นโปรแกรมจึงถูกเก็บไว้ในหน่วยความจำสำรอง เมื่อต้องการใช้โปรแกรมใดจะต้องเรียกโปรแกรมจากหน่วยความจำสำรองขึ้นมาเก็บในหน่วยความจำหลักเสียก่อนคอมพิวเตอร์จึงทำงานต่างๆต่อไปได้

ระบบปฎิบัติการ
ซอฟต์แวร์ที่สำคัญที่คอมพิวเตอร์จะต้องใช้คือระบบปฏิบัติการ(operating system)โดยซอฟแวร์ตัวนี้จะทำหน้าที่ควบคุมอุปกรณ์ทุกตัวที่ต่ออยู่กับระบบคอมพิวเตอร์ หน้าที่ต่างๆของระบบ ปฏิบัติการดังนี้
1. อ่านคำสั่งและทำตามคำสั่งที่ผู้ใช้พิมพ์เข้าไป
2. ควบคุมอุปกรณ์อินพุต เอาร์พุต
3. บอกข้อผิดพลาดต่างๆ
4. จัดการควบคุมหน่วยความจำ
ระบบปฏิบัติการที่นิยมใช้ในเครื่องคอมพิวเตอร์ IBM PC คือ Disk Operating System หรือ DOS ที่ใช้กันมีอยู่สองตัว คือ PC DOS และ MS DOS เมือ่คอมพิวเตอร์ทำงานจะถูกควบคุมโดยโปรแกรมดอสทันที หน้าที่สำคัญของดอสคืออ่านเขียนข้อมูลบนหน่วยความจำได้เมื่อคอมพิวเตอทำงานจะมีโปรแกรมย่อยตัวหนึ่งของ DOS ที่อยู่ในหน่วยควายจำสำรองคือโปรแกรม COMMAND.COM ซึ่งจะทำให้คอมพิวเตอร์รอรับคำสั่งและทำตามคำสั่งที่เราป้อนเข้าไป คำสั่งของ COMMAND.COM มีอยู่สองประเภทคือคำสั่งภายใน(internal) และคำสั่งภายนอก (extenal)
คำสั่งภายในของ command.com จะเป็นโปรแกรมย่อยของ ดอส ที่ถูกโหลดเข้าไปในหน่วยความจำและสามารถเรียกใช้ได้ทันทีคือคำสั่ง COPY,DIR,TIME เป็นต้น ส่วนคำสั่งภายนอกเมื่อเรียกใช้จะต้องมีไฟล์นั้นๆ อยู่ในหน่วยความจำสำรองเช่นคำสั่ง DISKCOPY,FORMAT เป็นต้น
โปรแกรม ดอส เป็นโปรแกรมที่อยู่ในแผ่นดิสก์หรือหน่วยความจำ ROM ระบบคอมพิวเตอร์ซึ่งเป็นโปรแกรมซึ่งมีประสิทธิภาพในการควบคุมฮาร์ดแวร์ต่างๆได้ดีกว่า เรียกโปรแกรม BIOS


โปรแกรม BIOS
BIOS เป็นโปรแกรมย่อยที่ควบคุมอุปกรณ์อินพุต เอาต์พุตของคอมพิวเตอร์ PC คล้ายๆกับโปรแกรมย่อยของ DOS แต่โปรแกรม BIOS จะเข้าถึงฮาร์ดแวร์ได้มากกว่าและโดยตรงกว่า DOS

หน่วยเชื่อมต่อบัส
หน่วยเชื่อมต่อบัสจะเป็นส่วนประกอบภายในไมโครโพเซสเซอร์ ทำหน้าที่อ่านรหัสคำสั่งจากหน่วยความจำเข้ามาเก็บใน CPU และทำตามคำสั่งนั้นที่เรียกว่า fetch,decode andexecute cycle
ในการอ่านหรัสคำสั่งจากหน่วยความจำมาเก็บในหน่วยเชื่อต่อบัส คำสั่งแต่ล่ะคำสั่งจะมีขนาดไม่เท่ากัน ความเร็วของการอ่านรหัสคำสั่งจะขึ้นกับความถี่สัญญาณนาฬิกาที่ป้อนให้กับ CPU ด้วย
ในหนังสือเล่มนี้รายละเอียดต่างๆ จะอ้างถึงไมโครโพรเซสเซอร์เบอร์ 8088 ซึ่งถือว่าเป็นพื้นฐานที่เข้าใจง่าย และสามารถนำคำสั่งต่างๆ ไปใช้กับไมโครโพรเซสเซอร์รุ่นสูงกว่าได้