人妻少妇精品久久久久久蜜臀av,久久综合激激的五月天,日韩精品无码专区免费播放,欧美精品999

索引越界(uibot數(shù)組索引越界)

前沿拓展:

索引越界

恢復(fù)軟件有時(shí)并不能完全正確恢復(fù)所有的文件,尤其是對(duì)格式化后的系統(tǒng)。
而且,EFS加密系統(tǒng)是對(duì)文件加密后存儲(chǔ)的,加密后的存儲(chǔ)報(bào)婷格式肯定與普通文件不同。而且這種加密是基于文件系統(tǒng)類型的。
可能是恢復(fù)軟件不能正確處理這種加密文件的某些具體參數(shù)。具體細(xì)節(jié)我也不清楚。

NTFS分區(qū)看看,能不能直接打開。


索引越界(uibot數(shù)組索引越界)

課程輸入 02 是以課程輸入 01 為基礎(chǔ)講解的,通過一個(gè)簡(jiǎn)單的命令行實(shí)現(xiàn)用戶的命令輸入和計(jì)算機(jī)的處理和顯示。

— Alex Chadwick

課程輸入 02 是以課程輸入 01 為基礎(chǔ)講解的,通過一個(gè)簡(jiǎn)單的命令行實(shí)現(xiàn)用戶的命令輸入和計(jì)算機(jī)的處理和顯示。本文假設(shè)你已經(jīng)具備 課程11:輸入01 的**作系統(tǒng)代碼基礎(chǔ)。

1、終端

幾乎所有的**作系統(tǒng)都是以字符終端顯示啟動(dòng)的。經(jīng)典的黑底白字,通過鍵盤輸入計(jì)算機(jī)要執(zhí)行的命令,第二會(huì)提示你拼寫錯(cuò)誤,或者恰好得到你想要的執(zhí)行結(jié)果。這種方法有兩個(gè)主要優(yōu)點(diǎn):鍵盤和顯示器可以提供簡(jiǎn)易、健壯的計(jì)算機(jī)交互機(jī)制,幾乎所有的計(jì)算機(jī)系統(tǒng)都采用這個(gè)機(jī)制,這個(gè)也廣泛被系統(tǒng)管理員應(yīng)用。

早期的計(jì)算一般是在一棟樓里的一個(gè)巨型計(jì)算機(jī)系統(tǒng),它有很多可以輸命令的’終端’。計(jì)算機(jī)依次執(zhí)行不同來源的命令。

讓我們分析下真正想要哪些信息:

計(jì)算機(jī)打開后,顯示歡迎信息計(jì)算機(jī)啟動(dòng)后可以接受輸入標(biāo)志用戶從鍵盤輸入帶參數(shù)的命令用戶輸入回車鍵或提交按鈕計(jì)算機(jī)解析命令后執(zhí)行可用的命令計(jì)算機(jī)顯示命令的執(zhí)行結(jié)果,過程信息循環(huán)跳轉(zhuǎn)到步驟 2

這樣的終端被定義為標(biāo)準(zhǔn)的輸入輸出設(shè)備。用于(顯示)輸入的屏幕和打印輸出內(nèi)容的屏幕是同一個(gè)(LCTT 譯注:最早期的輸出打印真是“打印”到打印機(jī)/電傳機(jī)的,而用于輸入的終端只是鍵盤,除非做了回顯,否則輸出終端是不會(huì)顯示輸入的字符的)。也就是說終端是對(duì)字符顯示的一個(gè)抽象。字符顯示中,單個(gè)字符是最小的單元,而不是像素。屏幕被劃分成固定數(shù)量不同顏色的字符。我們可以在現(xiàn)有的屏幕代碼基礎(chǔ)上,先存儲(chǔ)字符和對(duì)應(yīng)的顏色,第二再用方法 DrawCharacter 把其推送到屏幕上。一旦我們需要字符顯示,就只需要在屏幕上畫出一行字符串。

新建文件名為 terminal.s,如下:

.section .data

.align 4

terminalStart:

.int terminalBuffer

terminalStop:

.int terminalBuffer

terminalView:

.int terminalBuffer

terminalColour:

.byte 0xf

.align 8

terminalBuffer:

.rept 128*128

.byte 0x7f

.byte 0x0

.endr

terminalScreen:

.rept 1024/8 core.md Dict.md lctt2014.md lctt2016.md lctt2018.md LICENSE published README.md scripts sources translated 768/16

.byte 0x7f

.byte 0x0

.endr

這是文件終端的配置數(shù)據(jù)文件。我們有兩個(gè)主要的存儲(chǔ)變量:terminalBuffer 和 terminalScreen。terminalBuffer 保存所有顯示過的字符。它保存 128 行字符文本(1 行包含 128 個(gè)字符)。每個(gè)字符有一個(gè) ASCII 字符和顏色單元組成,初始值為 0x7f(ASCII 的刪除字符)和 0(前景色和背景色為黑)。terminalScreen 保存當(dāng)前屏幕顯示的字符。它保存 128×48 個(gè)字符,與 terminalBuffer 初始化值一樣。你可能會(huì)覺得我僅需要 terminalScreen 就夠了,為什么還要terminalBuffer,其實(shí)有兩個(gè)好處:

我們可以很容易看到字符串的變化,只需畫出有變化的字符。我們可以回滾終端顯示的歷史字符,也就是緩沖的字符(有限制)

這種獨(dú)特的技巧在低功耗系統(tǒng)里很常見。畫屏是很耗時(shí)的**作,因此我們僅在不得已的時(shí)候才去執(zhí)行這個(gè)**作。在這個(gè)系統(tǒng)里,我們可以任意改變 terminalBuffer,第二調(diào)用一個(gè)僅拷貝屏幕上字節(jié)變化的方法。也就是說我們不需要持續(xù)畫出每個(gè)字符,這樣可以節(jié)省一大段跨行文本的**作時(shí)間。

你總是需要嘗試去設(shè)計(jì)一個(gè)高效的系統(tǒng),如果在很少變化的情況下這個(gè)系統(tǒng)會(huì)運(yùn)行的更快。

其他在 .data 段的值得含義如下:

terminalStart 寫入到 terminalBuffer 的第一個(gè)字符terminalStop 寫入到 terminalBuffer 的最后一個(gè)字符terminalView 表示當(dāng)前屏幕的第一個(gè)字符,這樣我們可以控制滾動(dòng)屏幕temrinalColour 即將被描畫的字符顏色

terminalStart 需要保存起來的原因是 termainlBuffer 是一個(gè)環(huán)狀緩沖區(qū)。意思是當(dāng)緩沖區(qū)變滿時(shí),末尾地方會(huì)回滾覆蓋開始位置,這樣最后一個(gè)字符變成了第一個(gè)字符。因此我們需要將 terminalStart 往前推進(jìn),這樣我們知道我們已經(jīng)占滿它了。如何實(shí)現(xiàn)緩沖區(qū)檢測(cè):如果索引越界到緩沖區(qū)的末尾,就將索引指向緩沖區(qū)的開始位置。環(huán)狀緩沖區(qū)是一個(gè)比較常見的存儲(chǔ)大量數(shù)據(jù)的高明方法,往往這些數(shù)據(jù)的最近部分比較重要。它允許無限制的寫入,只保證最近一些特定數(shù)據(jù)有效。這個(gè)常常用于信號(hào)處理和數(shù)據(jù)壓縮算法。這樣的情況,可以允許我們存儲(chǔ) 128 行終端記錄,超過128行也不會(huì)有問題。如果不是這樣,當(dāng)超過第 128 行時(shí),我們需要把 127 行分別向前拷貝一次,這樣很浪費(fèi)時(shí)間。

索引越界(uibot數(shù)組索引越界)

顯示 Hellow world 插入到大小為5的循環(huán)緩沖區(qū)的示意圖。

環(huán)狀緩沖區(qū)是數(shù)據(jù)結(jié)構(gòu)一個(gè)例子。這是一個(gè)組織數(shù)據(jù)的思路,有時(shí)我們通過軟件實(shí)現(xiàn)這種思路。

之前已經(jīng)提到過 terminalColour 幾次了。你可以根據(jù)你的想法實(shí)現(xiàn)終端顏色,但這個(gè)文本終端有 16 個(gè)前景色和 16 個(gè)背景色(這里相當(dāng)于有 162 = 256 種組合)。 CGA 終端的顏色定義如下:

表格 1.1 – CGA 顏色編碼

序號(hào)顏色 (R, G, B)0黑 (0, 0, 0)1藍(lán) (0, 0, ?)2綠 (0, ?, 0)3青色 (0, ?, ?)4紅色 (?, 0, 0)5品紅 (?, 0, ?)6棕色 (?, ?, 0)7淺灰色 (?, ?, ?)8灰色 (?, ?, ?)9淡藍(lán)色 (?, ?, 1)10淡綠色 (?, 1, ?)11淡青色 (?, 1, 1)12淡紅色 (1, ?, ?)13淺品紅 (1, ?, 1)14** (1, 1, ?)15白色 (1, 1, 1)

我們將前景色保存到顏色的低字節(jié),背景色保存到顏色高字節(jié)。除了棕色,其他這些顏色遵循一種模式如二進(jìn)制的高位比特代表增加 ? 到每個(gè)組件,其他比特代表增加 ? 到各自組件。這樣很容易進(jìn)行 RGB 顏色轉(zhuǎn)換。

棕色作為替代色(黑**)既不吸引人也沒有什么用處。

我們需要一個(gè)方法從 TerminalColour 讀取顏色編碼的四個(gè)比特,第二用 16 比特等效參數(shù)調(diào)用 SetForeColour。嘗試你自己實(shí)現(xiàn)。如果你感覺麻煩或者還沒有完成屏幕系列課程,我們的實(shí)現(xiàn)如下:

.section .text

TerminalColour:

teq r0,#6

ldreq r0,=0x02B5

beq SetForeColour

tst r0,#0b1000

ldrne r1,=0x52AA

moveq r1,#0

tst r0,#0b0100

addne r1,#0x15

tst r0,#0b0010

addne r1,#0x540

tst r0,#0b0001

addne r1,#0xA800

mov r0,r1

b SetForeColour

2、文本顯示

我們的終端第一個(gè)真正需要的方法是 TerminalDisplay,它用來把當(dāng)前的數(shù)據(jù)從 terminalBuffer拷貝到 terminalScreen 和實(shí)際的屏幕。如上所述,這個(gè)方法必須是最小開銷的**作,因?yàn)槲覀冃枰l繁調(diào)用它。它主要比較 terminalBuffer 與 terminalDisplay 的文本,第二只拷貝有差異的字節(jié)。請(qǐng)記住 terminalBuffer 是以環(huán)狀緩沖區(qū)運(yùn)行的,這種情況,就是從 terminalView 到 terminalStop,或者 128*48 個(gè)字符,要看哪個(gè)來的最快。如果我們遇到 terminalStop,我們將會(huì)假定在這之后的所有字符是 7f16 (ASCII 刪除字符),顏色為 0(黑色前景色和背景色)。

讓我們看看必須要做的事情:

加載 terminalView、terminalStop 和 terminalDisplay 的地址。對(duì)于每一行:對(duì)于每一列:如果 terminalView 不等于 terminalStop,根據(jù) terminalView 加載當(dāng)前字符和顏色否則加載 0x7f 和顏色 0從 terminalDisplay 加載當(dāng)前的字符如果字符和顏色相同,直接跳轉(zhuǎn)到第 10 步存儲(chǔ)字符和顏色到 terminalDisplay用 r0 作為背景色參數(shù)調(diào)用 TerminalColour用 r0 = 0x7f(ASCII 刪除字符,一個(gè)塊)、 r1 = x、r2 = y 調(diào)用 DrawCharacter用 r0 作為前景色參數(shù)調(diào)用 TerminalColour用 r0 = 字符、r1 = x、r2 = y 調(diào)用 DrawCharacter對(duì)位置參數(shù) terminalDisplay 累加 2如果 terminalView 不等于 terminalStop,terminalView 位置參數(shù)累加 2如果 terminalView 位置已經(jīng)是文件緩沖器的末尾,將它設(shè)置為緩沖區(qū)的開始位置x 坐標(biāo)增加 8y 坐標(biāo)增加 16

嘗試去自己實(shí)現(xiàn)吧。如果你遇到問題,我們的方案下面給出來了:

1、我這里的變量有點(diǎn)亂。為了方便起見,我用 taddr 存儲(chǔ) textBuffer 的末尾位置。

.globl TerminalDisplay

TerminalDisplay:

push {r4,r5,r6,r7,r8,r9,r10,r11,lr}

x .req r4

y .req r5

char .req r6

col .req r7

screen .req r8

taddr .req r9

view .req r10

stop .req r11

ldr taddr,=terminalStart

ldr view,[taddr,#terminalView – terminalStart]

ldr stop,[taddr,#terminalStop – terminalStart]

add taddr,#terminalBuffer – terminalStart

add taddr,#128*128*2

mov screen,taddr

2、從 yLoop 開始運(yùn)行。

mov y,#0

yLoop$:

2.1、

mov x,#0

xLoop$:

從 xLoop 開始運(yùn)行。

2.1.1、為了方便起見,我把字符和顏色同時(shí)加載到 char 變量了

teq view,stop

ldrneh char,[view]

2.1.2、這行是對(duì)上面一行的補(bǔ)充說明:讀取黑色的刪除字符

moveq char,#0x7f

2.1.3、為了簡(jiǎn)便我把字符和顏色同時(shí)加載到 col 里。

ldrh col,[screen]

2.1.4、 現(xiàn)在我用 teq 指令檢查是否有數(shù)據(jù)變化

teq col,char

beq xLoopContinue$

2.1.5、我可以容易的保存當(dāng)前值

strh char,[screen]

2.1.6、我用比特偏移指令 lsr 和 and 指令從切分 char 變量,將顏色放到 col 變量,字符放到 char 變量,第二再用比特偏移指令 lsr 獲取背景色后調(diào)用 TerminalColour 。

lsr col,char,#8

and char,#0x7f

lsr r0,col,#4

bl TerminalColour

2.1.7、寫入一個(gè)彩色的刪除字符

mov r0,#0x7f

mov r1,x

mov r2,y

bl DrawCharacter

2.1.8、用 and 指令獲取 col 變量的低半字節(jié),第二調(diào)用 TerminalColour

and r0,col,#0xf

bl TerminalColour

2.1.9、寫入我們需要的字符

mov r0,char

mov r1,x

mov r2,y

bl DrawCharacter

2.1.10、自增屏幕指針

xLoopContinue$:

add screen,#2

2.1.11、如果可能自增 view 指針

teq view,stop

addne view,#2

2.1.12、很容易檢測(cè) view 指針是否越界到緩沖區(qū)的末尾,因?yàn)榫彌_區(qū)的地址保存在 taddr 變量里

teq view,taddr

subeq view,#128*128*2

2.1.13、 如果還有字符需要顯示,我們就需要自增 x 變量第二到 xLoop 循環(huán)執(zhí)行

add x,#8

teq x,#1024

bne xLoop$

2.2、 如果還有更多的字符顯示我們就需要自增 y 變量,第二到 yLoop 循環(huán)執(zhí)行

add y,#16

teq y,#768

bne yLoop$

3、不要忘記最后清除變量

pop {r4,r5,r6,r7,r8,r9,r10,r11,pc}

.unreq x

.unreq y

.unreq char

.unreq col

.unreq screen

.unreq taddr

.unreq view

.unreq stop

3、行打印

現(xiàn)在我有了自己 TerminalDisplay 方法,它可以自動(dòng)顯示 terminalBuffer 內(nèi)容到 terminalScreen,因此理論上我們可以畫出文本。但是實(shí)際上我們沒有任何基于字符顯示的例程。 第一快速容易上手的方法便是 TerminalClear, 它可以徹底清除終端。這個(gè)方法不用循環(huán)也很容易實(shí)現(xiàn)??梢試L試分析下面的方法應(yīng)該不難:

.globl TerminalClear

TerminalClear:

ldr r0,=terminalStart

add r1,r0,#terminalBuffer-terminalStart

str r1,[r0]

str r1,[r0,#terminalStop-terminalStart]

str r1,[r0,#terminalView-terminalStart]

mov pc,lr

現(xiàn)在我們需要構(gòu)造一個(gè)字符顯示的基礎(chǔ)方法:Print 函數(shù)。它將保存在 r0 的字符串和保存在 r1 的字符串長(zhǎng)度簡(jiǎn)單的寫到屏幕上。有一些特定字符需要特別的注意,這些特定的**作是確保 terminalView 是最新的。我們來分析一下需要做什么:

檢查字符串的長(zhǎng)度是否為 0,如果是就直接返回加載 terminalStop 和 terminalView計(jì)算出 terminalStop 的 x 坐標(biāo)對(duì)每一個(gè)字符的**作:檢查字符是否為新起一行如果是的話,自增 bufferStop 到行末,同時(shí)寫入黑色刪除字符否則拷貝當(dāng)前 terminalColour 的字符檢查是否在行末如果是,檢查從 terminalView 到 terminalStop 之間的字符數(shù)是否大于一屏如果是,terminalView 自增一行檢查 terminalView 是否為緩沖區(qū)的末尾,如果是的話將其替換為緩沖區(qū)的起始位置檢查 terminalStop 是否為緩沖區(qū)的末尾,如果是的話將其替換為緩沖區(qū)的起始位置檢查 terminalStop 是否等于 terminalStart, 如果是的話 terminalStart 自增一行。檢查 terminalStart 是否為緩沖區(qū)的末尾,如果是的話將其替換為緩沖區(qū)的起始位置存取 terminalStop 和 terminalView

試一下自己去實(shí)現(xiàn)。我們的方案提供如下:

1、這個(gè)是 Print 函數(shù)開始快速檢查字符串為0的代碼

.globl Print

Print:

teq r1,#0

moveq pc,lr

2、這里我做了很多配置。 bufferStart 代表 terminalStart, bufferStop 代表terminalStop, view 代表 terminalView,taddr 代表 terminalBuffer 的末尾地址。

push {r4,r5,r6,r7,r8,r9,r10,r11,lr}

bufferStart .req r4

taddr .req r5

x .req r6

string .req r7

length .req r8

char .req r9

bufferStop .req r10

view .req r11

mov string,r0

mov length,r1

ldr taddr,=terminalStart

ldr bufferStop,[taddr,#terminalStop-terminalStart]

ldr view,[taddr,#terminalView-terminalStart]

ldr bufferStart,[taddr]

add taddr,#terminalBuffer-terminalStart

add taddr,#128*128*2

3、和通常一樣,巧妙的對(duì)齊技巧讓許多事情更容易。由于需要對(duì)齊 terminalBuffer,每個(gè)字符的 x 坐標(biāo)需要 8 位要除以 2。

and x,bufferStop,#0xfe

lsr x,#1

4.1、我們需要檢查新行

charLoop$:

ldrb char,[string]

and char,#0x7f

teq char,#’n’

bne charNormal$

4.2、循環(huán)執(zhí)行值到行末寫入 0x7f;黑色刪除字符

mov r0,#0x7f

clearLine$:

strh r0,[bufferStop]

add bufferStop,#2

add x,#1

teq x,#128 blt clearLine$

b charLoopContinue$

4.3、存儲(chǔ)字符串的當(dāng)前字符和 terminalBuffer 末尾的 terminalColour 第二將它和 x 變量自增

charNormal$:

strb char,[bufferStop]

ldr r0,=terminalColour

ldrb r0,[r0]

strb r0,[bufferStop,#1]

add bufferStop,#2

add x,#1

4.4、檢查 x 是否為行末;128

charLoopContinue$:

cmp x,#128

blt noScroll$

4.5、設(shè)置 x 為 0 第二檢查我們是否已經(jīng)顯示超過 1 屏。請(qǐng)記住,我們是用的循環(huán)緩沖區(qū),因此如果 bufferStop 和 view 之前的差是負(fù)值,我們實(shí)際上是環(huán)繞了緩沖區(qū)。

mov x,#0

subs r0,bufferStop,view

addlt r0,#128*128*2

cmp r0,#128*(768/16)*2

4.6、增加一行字節(jié)到 view 的地址

addge view,#128*2

4.7、 如果 view 地址是緩沖區(qū)的末尾,我們就從它上面減去緩沖區(qū)的長(zhǎng)度,讓其指向開始位置。我會(huì)在開始的時(shí)候設(shè)置 taddr 為緩沖區(qū)的末尾地址。

teq view,taddr

subeq view,taddr,#128*128*2

4.8、如果 stop 的地址在緩沖區(qū)末尾,我們就從它上面減去緩沖區(qū)的長(zhǎng)度,讓其指向開始位置。我會(huì)在開始的時(shí)候設(shè)置 taddr 為緩沖區(qū)的末尾地址。

noScroll$:

teq bufferStop,taddr

subeq bufferStop,taddr,#128*128*2

4.9、檢查 bufferStop 是否等于 bufferStart。 如果等于增加一行到 bufferStart。

teq bufferStop,bufferStart

addeq bufferStart,#128*2

4.10、如果 start 的地址在緩沖區(qū)的末尾,我們就從它上面減去緩沖區(qū)的長(zhǎng)度,讓其指向開始位置。我會(huì)在開始的時(shí)候設(shè)置 taddr 為緩沖區(qū)的末尾地址。

teq bufferStart,taddr

subeq bufferStart,taddr,#128*128*2

循環(huán)執(zhí)行知道字符串結(jié)束

subs length,#1

add string,#1

bgt charLoop$

5、保存變量第二返回

charLoopBreak$:

sub taddr,#128*128*2

sub taddr,#terminalBuffer-terminalStart

str bufferStop,[taddr,#terminalStop-terminalStart]

str view,[taddr,#terminalView-terminalStart]

str bufferStart,[taddr]

pop {r4,r5,r6,r7,r8,r9,r10,r11,pc}

.unreq bufferStart

.unreq taddr

.unreq x

.unreq string

.unreq length

.unreq char

.unreq bufferStop

.unreq view

這個(gè)方法允許我們打印任意字符到屏幕。然而我們用了顏色變量,但實(shí)際上沒有設(shè)置它。一般終端用特性的組合字符去行修改顏色。如 ASCII 轉(zhuǎn)義(1b16)后面跟著一個(gè) 0 – f 的 16 進(jìn)制的數(shù),就可以設(shè)置前景色為 CGA 顏色號(hào)。如果你自己想嘗試實(shí)現(xiàn);在下載頁面有一個(gè)我的詳細(xì)的例子。

4、標(biāo)志輸入

現(xiàn)在我們有一個(gè)可以打印和顯示文本的輸出終端。這僅僅是說對(duì)了一半,我們需要輸入。我們想實(shí)現(xiàn)一個(gè)方法:ReadLine,可以保存文件的一行文本,文本位置由 r0 給出,最大的長(zhǎng)度由 r1 給出,返回 r0 里面的字符串長(zhǎng)度。棘手的是用戶輸出字符的時(shí)候要回顯功能,同時(shí)想要退格鍵的刪除功能和命令回車執(zhí)行功能。它們還需要一個(gè)閃爍的下劃線代表計(jì)算機(jī)需要輸入。這些完全合理的要求讓構(gòu)造這個(gè)方法更具有挑戰(zhàn)性。有一個(gè)方法完成這些需求就是存儲(chǔ)用戶輸入的文本和文件大小到內(nèi)存的某個(gè)地方。第二當(dāng)調(diào)用 ReadLine 的時(shí)候,移動(dòng) terminalStop 的地址到它開始的地方第二調(diào)用 Print。也就是說我們只需要確保在內(nèi)存維護(hù)一個(gè)字符串,第二構(gòu)造一個(gè)我們自己的打印函數(shù)。

按照慣例,許多編程語言中,任意程序可以訪問 stdin 和 stdin,它們可以連接到終端的輸入和輸出流。在圖形程序其實(shí)也可以進(jìn)行同樣**作,但實(shí)際幾乎不用。

讓我們看看 ReadLine 做了哪些事情:

如果字符串可保存的最大長(zhǎng)度為 0,直接返回檢索 terminalStop 和 terminalStop 的當(dāng)前值如果字符串的最大長(zhǎng)度大約緩沖區(qū)的一半,就設(shè)置大小為緩沖區(qū)的一半從最大長(zhǎng)度里面減去 1 來確保輸入的閃爍字符或結(jié)束符向字符串寫入一個(gè)下劃線寫入一個(gè) terminalView 和 terminalStop 的地址到內(nèi)存調(diào)用 Print 打印當(dāng)前字符串調(diào)用 TerminalDisplay調(diào)用 KeyboardUpdate調(diào)用 KeyboardGetChar如果是一個(gè)新行直接跳轉(zhuǎn)到第 16 步如果是一個(gè)退格鍵,將字符串長(zhǎng)度減 1(如果其大于 0)如果是一個(gè)普通字符,將它寫入字符串(字符串大小確保小于最大值)如果字符串是以下劃線結(jié)束,寫入一個(gè)空格,否則寫入下劃線跳轉(zhuǎn)到第 6 步字符串的末尾寫入一個(gè)新行字符調(diào)用 Print 和 TerminalDisplay用結(jié)束符替換新行返回字符串的長(zhǎng)度

為了方便讀者理解,第二第二自己去實(shí)現(xiàn),我們的實(shí)現(xiàn)提供如下:

快速處理長(zhǎng)度為 0 的情況

.globl ReadLine

ReadLine:

teq r1,#0

moveq r0,#0

moveq pc,lr

2、考慮到常見的場(chǎng)景,我們初期做了很多初始化動(dòng)作。input 代表 terminalStop 的值,view 代表 terminalView。Length 默認(rèn)為 0。

string .req r4

maxLength .req r5

input .req r6

taddr .req r7

length .req r8

view .req r9

push {r4,r5,r6,r7,r8,r9,lr}

mov string,r0

mov maxLength,r1

ldr taddr,=terminalStart

ldr input,[taddr,#terminalStop-terminalStart]

ldr view,[taddr,#terminalView-terminalStart]

mov length,#0

3、我們必須檢查異常大的讀**作,我們不能處理超過 terminalBuffer 大小的輸入(理論上可行,但是 terminalStart 移動(dòng)越過存儲(chǔ)的 terminalStop`,會(huì)有很多問題)。

cmp maxLength,#128*64

movhi maxLength,#128*64

4、由于用戶需要一個(gè)閃爍的光標(biāo),我們需要一個(gè)備用字符在理想狀況在這個(gè)字符串后面放一個(gè)結(jié)束符。

sub maxLength,#1

5、寫入一個(gè)下劃線讓用戶知道我們可以輸入了。

mov r0,#’_’

strb r0,[string,length]

6、保存 terminalStop 和 terminalView。這個(gè)對(duì)重置一個(gè)終端很重要,它會(huì)修改這些變量。嚴(yán)格講也可以修改 terminalStart,但是不可逆。

readLoop$:

str input,[taddr,#terminalStop-terminalStart]

str view,[taddr,#terminalView-terminalStart]

7、寫入當(dāng)前的輸入。由于下劃線因此字符串長(zhǎng)度加 1

mov r0,string

mov r1,length

add r1,#1

bl Print

8、拷貝下一個(gè)文本到屏幕

bl TerminalDisplay

9、獲取最近一次鍵盤輸入

bl KeyboardUpdate

10、檢索鍵盤輸入鍵值

bl KeyboardGetChar

11、如果我們有一個(gè)回車鍵,循環(huán)中斷。如果有結(jié)束符和一個(gè)退格鍵也會(huì)同樣跳出循環(huán)。

teq r0,#’n’

beq readLoopBreak$

teq r0,#0

beq cursor$

teq r0,#’b’

bne standard$

12、從 length 里面刪除一個(gè)字符

delete$:

cmp length,#0

subgt length,#1

b cursor$

13、寫回一個(gè)普通字符

standard$:

cmp length,maxLength

bge cursor$

strb r0,[string,length]

add length,#1

14、加載最近的一個(gè)字符,如果不是下劃線則修改為下?lián)Q線,如果是則修改為空格

cursor$:

ldrb r0,[string,length]

teq r0,#’_’

moveq r0,#’ ‘

movne r0,#’_’

strb r0,[string,length]

15、循環(huán)執(zhí)行值到用戶輸入按下

b readLoop$

readLoopBreak$:

16、在字符串的結(jié)尾處存入一個(gè)新行字符

mov r0,#’n’

strb r0,[string,length]

17、重置 terminalView 和 terminalStop 第二調(diào)用 Print 和 TerminalDisplay 顯示最終的輸入

str input,[taddr,#terminalStop-terminalStart]

str view,[taddr,#terminalView-terminalStart]

mov r0,string

mov r1,length

add r1,#1

bl Print

bl TerminalDisplay

18、寫入一個(gè)結(jié)束符

mov r0,#0

strb r0,[string,length]

19、返回長(zhǎng)度

mov r0,length

pop {r4,r5,r6,r7,r8,r9,pc}

.unreq string

.unreq maxLength

.unreq input

.unreq taddr

.unreq length

.unreq view

5、終端:機(jī)器進(jìn)化

現(xiàn)在我們理論用終端和用戶可以交互了。最顯而易見的事情就是拿去測(cè)試了!刪除 main.s 里 bl U**Initialise 后面的代碼后如下:

reset$:

mov sp,#0x8000

bl TerminalClear

ldr r0,=welcome

mov r1,#welcomeEnd-welcome

bl Print

loop$:

ldr r0,=prompt

mov r1,#promptEnd-prompt

bl Print

ldr r0,=command

mov r1,#commandEnd-command

bl ReadLine

teq r0,#0

beq loopContinue$

mov r4,r0

ldr r5,=command

ldr r6,=commandTable

ldr r7,[r6,#0]

ldr r9,[r6,#4]

commandLoop$:

ldr r8,[r6,#8]

sub r1,r8,r7

cmp r1,r4

bgt commandLoopContinue$

mov r0,#0

commandName$:

ldrb r2,[r5,r0]

ldrb r3,[r7,r0]

teq r2,r3

bne commandLoopContinue$

add r0,#1

teq r0,r1

bne commandName$

ldrb r2,[r5,r0]

teq r2,#0

teqne r2,#’ ‘

bne commandLoopContinue$

mov r0,r5

mov r1,r4

mov lr,pc

mov pc,r9

b loopContinue$

commandLoopContinue$:

add r6,#8

mov r7,r8

ldr r9,[r6,#4]

teq r9,#0

bne commandLoop$

ldr r0,=commandUnknown

mov r1,#commandUnknownEnd-commandUnknown

ldr r2,=formatBuffer

ldr r3,=command

bl FormatString

mov r1,r0

ldr r0,=formatBuffer

bl Print

loopContinue$:

bl TerminalDisplay

b loop$

echo:

cmp r1,#5

movle pc,lr

add r0,#5

sub r1,#5

b Print

ok:

teq r1,#5

beq okOn$

teq r1,#6

beq okOff$

mov pc,lr

okOn$:

ldrb r2,[r0,#3]

teq r2,#’o’

ldreqb r2,[r0,#4]

teqeq r2,#’n’

movne pc,lr

mov r1,#0

b okAct$

okOff$:

ldrb r2,[r0,#3]

teq r2,#’o’

ldreqb r2,[r0,#4]

teqeq r2,#’f’

ldreqb r2,[r0,#5]

teqeq r2,#’f’

movne pc,lr

mov r1,#1

okAct$:

mov r0,#16

b SetGpio

.section .data

.align 2

welcome: .ascii “Welcome to Alex’s OS – Everyone’s favourite OS”

welcomeEnd:

.align 2

prompt: .ascii “n> ”

promptEnd:

.align 2

command:

.rept 128

.byte 0

.endr

commandEnd:

.byte 0

.align 2

commandUnknown: .ascii “Command `%s’ was not recognised.n”

commandUnknownEnd:

.align 2

formatBuffer:

.rept 256

.byte 0

.endr

formatEnd:

.align 2

commandStringEcho: .ascii “echo”

commandStringReset: .ascii “reset”

commandStringOk: .ascii “ok”

commandStringCls: .ascii “cls”

commandStringEnd:

.align 2

commandTable:

.int commandStringEcho, echo

.int commandStringReset, reset$

.int commandStringOk, ok

.int commandStringCls, TerminalClear

.int commandStringEnd, 0

這塊代碼集成了一個(gè)簡(jiǎn)易的命令行**作系統(tǒng)。支持命令:echo、reset、ok 和 cls。echo 拷貝任意文本到終端,reset 命令會(huì)在系統(tǒng)出現(xiàn)問題的是復(fù)位**作系統(tǒng),ok 有兩個(gè)功能:設(shè)置 OK 燈亮滅,最后 cls 調(diào)用 TerminalClear 清空終端。

試試樹莓派的代碼吧。如果遇到問題,請(qǐng)參照問題集錦頁面吧。

如果運(yùn)行正常,祝賀你完成了一個(gè)**作系統(tǒng)基本終端和輸入系列的課程。很遺憾這個(gè)教程先講到這里,但是我希望將來能制作更多教程。有問題請(qǐng)反饋至 awc32@cam.ac.uk 。

你已經(jīng)在建立了一個(gè)簡(jiǎn)易的終端**作系統(tǒng)。我們的代碼在 commandTable 構(gòu)造了一個(gè)可用的命令表格。每個(gè)表格的入口是一個(gè)整型數(shù)字,用來表示字符串的地址,和一個(gè)整型數(shù)字表格代碼的執(zhí)行入口。 最后一個(gè)入口是 為 0 的 commandStringEnd。嘗試實(shí)現(xiàn)你自己的命令,可以參照已有的函數(shù),建立一個(gè)新的。函數(shù)的參數(shù) r0 是用戶輸入的命令地址,r1 是其長(zhǎng)度。你可以用這個(gè)傳遞你輸入值到你的命令。也許你有一個(gè)計(jì)算器程序,或許是一個(gè)繪圖程序或國(guó)際象棋。不管你的什么點(diǎn)子,讓它跑起來!

via: https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/os/input02.html

作者: Alex Chadwick 選題: lujun9972 譯者: guevaraya 校對(duì): wxy

本文由 LCTT 原創(chuàng)編譯, Linux** 榮譽(yù)推出

點(diǎn)擊“了解更多”可訪問文內(nèi)鏈接

拓展知識(shí):

索引越界

里面都是百度的軟件,這吧不是網(wǎng)友開的,都是百度工作人員發(fā)百度專用的軟件上去。。
比如我現(xiàn)在就用的:
百度貼把伴侶(實(shí)際上就是百度專用的瀏覽器。)
百度貼吧數(shù)據(jù)統(tǒng)計(jì)工具(就是把貼吧的影響力排名的軟件)
。。。。。。。。。。
還有很多,去那個(gè)吧里看看吧/。

原創(chuàng)文章,作者:九賢生活小編,如若轉(zhuǎn)載,請(qǐng)注明出處:http://m.xiesong.cn/36564.html

无码激情视频中文字幕| 日韩精品一区二区无码| 欧美亚州中文| 亚洲一区导航| 中文字幕黄色| 18禁美女黄色网站| 超碰人中文字幕| 狠狠人妻久久久蜜桃| 久久久久国产精品熟女影院| 日韩人妻无码第17页| 日本一本蒙三级| 日韩免费视频一区| 亚洲区少妇| 欧美高清一区二区三| A级片网站| 欧美另类日韩| 99亚洲免费视频| 久久91AV免费观看| 亚洲Av之男人的天堂| 国产91天堂色| 欧美日韩精品久久香蕉| 凹凸久久人人澡超碰凹凸| 女自慰喷水免费观看WWW久久| 好看的露脸内射| 在线视频日韩精品| 欧美47| 亚洲成熟丰满熟妇高潮XXXXX | av久操伊人| 奇米影视一区二区三区| 无码人妻丝袜在线视频| 噜噜色区| 超碰无码AⅤ| 亚洲国产成人精品女人久| 欧美丰满熟妇XXXX| 欧美亚洲特级黄片| 超碰在线少妇| 日韩av在线电影一区| 免费高清自慰一区二区三区| 你懂得视频网址| 日韩一=三四五区| 亚洲无线观看国产精品|