彙編裏的轉移指令是真多啊....函數
首先,在機器碼裏,轉移不會給定目的地址,而是給出相對位移oop
1)無條件轉移指令spa
jump short label // 段內轉移 ip + 8位位移code
jump near ptr label // 段內轉移 ip + 16位位移blog
jump far ptr label // 段間轉移 cs:label所在段的段地址,ip:label所在段的偏移地址ip
jump 16位reg // ip = (reg)內存
2)條件轉移指令it
jcxz label // 當cx=0時就轉移到label ip + 8位位移class
因此loop的內部機制就是jcxz:LOOP,使用計數器 cx。進入循環前設置好,每循環一次自動-1.循環
3)call和ret
call label // 先push call下一條語句的ip,再jump near ptr label;相似的有 call far ptr label:依次push cs、push ip、jump far ptr label
ret // 先pop ip,再根據ip執行指令 ;相似的有 retf:依次pop ip、pop cs,再執行指令
雙劍合璧,想一想都很厲害,子程序順溜地來。
說到子程序,想起了VM language裏的函數。
函數調用的流程是:先push主程序的一系列段地址以及returnAddress(這個是專門定義的一個label),再修改ARG令其指向實參,而後執行label後的語句,執行完先返回參數,再pop主程序的段地址,再goto returnAddress。
實際中使用的彙編語言處理子程序的流程相似:遇到call指令,先push ip或ip和cs,再執行子程序(在子程序裏有時也會對寄存器內容進行入棧出棧操做),子程序結束處有ret,用於pop ip或ip和cs。
因此,Nand2Teris就是提供了一種實現計算機的基本思路,一通百通型。
舉個栗子:顯示器大小爲25*80,即25行,每行80個字,每一個字由兩部分組成:一個字節表示字符,一個字節表示屬性(顏色背景)
請在顯示器的第13行、35列顯示
Have fun with Assembly
慢慢來。
(1)怎麼在顯示器上顯示字符?
顯示器的段地址默認爲B800h,利用偏移地址修改內存單元的內容便可。偏移地址爲奇數就存放字符,偶數存放對應的屬性。
(2)怎麼在設置顯示字符的屬性?
屬性由一個字節控制,即8個bite,分別爲 閃爍 背景RGB 高亮 前景RGB,選擇0/1。
好比說閃爍紅底綠字就是 11000010B;黑底白字就是 00000111B
(3)怎麼顯示一串字符?
很容易想到循環。
其實這上面這些概念性的都好理解,很差弄的是寄存器的使用和計算,須要考慮8位仍是16位,數據在寄存器間的傳送,寄存器不夠了咋整等等。
assume cs:code
data segment
db 'Have fun with Assembly!',0 data ends code segment start: mov dh,13 mov dl,35 mov cl,2 mov ax,data mov ds,ax mov si,0 call show_str mov ax,4c00h int 21h show_str:sub dh,1 mov al,160 mul dh mov bx,ax sub dl,1 mov al,2 mul dl add ax,bx mov bx,ax mov ax,0B800h mov es,ax mov al,cl captical:mov cl,ds:[si] mov ch,0 jcxz ok mov di,ds:[si] mov byte ptr es:[bx],di inc bx mov byte ptr es:[bx],al inc bx inc si jmp short captical ok: ret code ends end start