2014-10-08 44 views
2

目標:
我需要編寫一個程序,測試整個1MB內存的寫入功能,逐字節地爲一個系統使用英特爾80186微處理器。換句話說,我需要向內存中的每個字節寫入0,然後檢查是否實際寫入了0。然後,我需要使用值1重複此過程。最後,任何未成功寫入0或1的內存位置都需要存儲在堆棧中。x86程序集:編寫一個程序來測試整個1MB內存的內存功能

討論:
我是一名電子工程專業的大學生(不是計算機科學專業),而且對於x86彙編語言和MASM611來說還是比較新的。我沒有尋找完整的解決方案。不過,我需要一些指導。

在本學期的早些時候,我寫了一個程序,用0填充了一部分內存。我相信這將是我目前項目的一個很好的起點。

源代碼早期程序:

;**************************************************************************** 
;Program Name: Zeros 
;File Name: PROJ01.ASM 
;DATE: 09/16/14 
;FUNCTION: FILL A MEMORY SEGMENT WITH ZEROS 
;HISTORY: 
;AUTHOR(S): 
;**************************************************************************** 

NAME ZEROS 

MYDATA SEGMENT 
MYDATA ENDS 

MYSTACK SEGMENT STACK 
       DB    0FFH DUP(?) 
       End_Of_Stack LABEL BYTE 
MYSTACK ENDS 



ASSUME SS:MYSTACK, DS:MYDATA, CS:MYCODE 
MYCODE SEGMENT 
START: MOV AX, MYSTACK 
     MOV SS, AX 
     MOV SP, OFFSET End_Of_Stack 
     MOV AX, MYDATA 
     MOV DS, AX 

     MOV AX, 0FFFFh     ;Moves a Hex value of 65535 into AX 
     MOV BX, 0000h     ;Moves a Hex value of 0 into BX 

     CALL Zero_fill     ;Calls procedure Zero_fill 

     MOV AX, 4C00H     ;Performs a clean exit 
     INT 21H 

Zero_fill PROC NEAR     ;Declares procedure Zero_fill with near directive 
       MOV DX, 0000h   ;Moves 0H into DX 
       MOV CX, 0000h   ;Moves 0H into CX. This will act as a counter. 
Start_Repeat: INC CX     ;Increments CX by 1 
       MOV [BX], DX   ;Moves the contents of DX to the memory address of BX 
       INC BX     ;Increments BX by 1 
       CMP CX, 10000h   ;Compares the value of CX with 10000H. If equal, Z-flag set to one. 
       JNE Start_Repeat  ;Jumps to Start_Repeat if CX does not equal 10000H. 
       RET      ;Removes 16-bit value from stack and puts it in IP 
Zero_fill ENDP      ;Ends procedure Zero_fill 

MYCODE ENDS 
END START 

要求:
1.錄用明確的段結構。
2.使用ES:DI寄存器對尋址測試存儲區。
3.非破壞性訪問:在測試每個內存位置之前,我需要存儲該字節的原始內容。測試完成後需要恢復哪些內容。
4.我需要存儲在堆棧上測試失敗的任何內存位置的地址。
5.我需要確定最高的RAM位置。

計劃:
1.在一個循環:寫0000H到存儲位置,在那個位置MEM校驗值,ES和DI的PUSH值到堆棧,如果檢查失敗。
2.在循環中:將FFFFH寫入內存位置,檢查該內存位置的值,如果檢查失敗,則檢查堆棧中ES和DI的值爲PUSH

源代碼實施預案:

;**************************************************************************** 
;Program Name: Memory Test 
;File Name: M_TEST.ASM 
;DATE: 10/7/14 
;FUNCTION: Test operational status of each byte of memory between a starting 
;   location and an ending location 
;HISTORY: Template code from Assembly Project 1 
;AUTHOR(S): 
;**************************************************************************** 

NAME M_TEST 

MYDATA SEGMENT 
MYDATA ENDS 

MYSTACK SEGMENT STACK 
       DB    0FFH DUP(?) 
       End_Of_Stack LABEL BYTE 
MYSTACK ENDS 

ESTACK SEGMENT COMMON 
ESTACK ENDS 

ASSUME SS:MYSTACK, DS:MYDATA, CS:MYCODE, ES:ESTACK 
MYCODE SEGMENT 
START:   MOV AX, MYSTACK 
       MOV SS, AX 
       MOV SP, OFFSET End_Of_Stack 
       MOV AX, MYDATA 
       MOV DS, AX 

       MOV AX, FFFFH   ;Moves a Hex value of 65535 into AX 
       MOV BX, 0000H   ;Moves a Hex value of 0 into BX 

       CALL M_TEST    ;Calls procedure M_TEST 

       MOV AX, 4C00H   ;Performs a clean exit 
       INT 21H 

M_TEST  PROC NEAR     ;Declares procedure M_TEST with near directive 
       MOV DX, 0000H   ;Fill DX with 0's 
       MOV AX, FFFFH   ;Fill AX with 1's 
       MOV CX, 0000H   ;Moves 0H into CX. This will act as a counter. 
Start_Repeat: MOV [BX], DX   ;Moves the contents of DX to the memory address of BX 
       CMP [BX], 0000H   ;Compare value at memory location [BX] with 0H. If equal, Z-flag set to one. 
       JNE SAVE    ;IF Z-Flag NOT EQUAL TO 0, Jump TO SAVE 
       MOV [BX], AX   ;Moves the contents of AX to the memory address of BX 
       CMP [BX], FFFFH   ;Compare value at memory location [BX] with FFFFH. If equal, Z-flag set to one. 
       JNE SAVE    ;IF Z-Flag NOT EQUAL TO 0, Jump TO SAVE 
       INC CX     ;Increments CX by 1 
       INC BX     ;Increments BX by 1 
       CMP CX, 10000H   ;Compares the value of CX with 10000H. If equal, Z-flag set to one. 
       JNE Start_Repeat  ;Jumps to Start_Repeat if CX does not equal 10000H. 
SAVE:   PUSH ES 
       PUSH DI 
       RET      ;Removes 16-bit value from stack and puts it in IP 
M_TEST  ENDP      ;Ends procedure Zero_fill 

MYCODE ENDS 
END START 

我的評論可能不準確。

問題:
1.如何使用ES:DI來尋址測試存儲區?
2.什麼是保持初始內存值的最佳方式,以便在完成特定內存位置測試後可以替換它?我相信註冊AX - DX已經在使用。另外,如果我更新了代碼和問題,是否應該將它發佈在同一個線程中,還是應該創建一個新鏈接以指向此鏈接?

任何其他意見將不勝感激。
在此先感謝。

+0

關於要求#3,您可以在哪裏保存您正在測試的區域? – 2014-10-08 02:40:41

+0

他是否讓你離開這條指令? 'CMP CX,10000h' – 2014-10-08 02:43:21

+0

首先,關於Req沒有指定區域。其次,我相信'CMP CX,10000H'是允許的。有沒有理由不應該這樣? – Ben 2014-10-10 17:56:38

回答

0

如何使用ES:DI來尋址測試存儲區?

例如,mov al, es:[di]

什麼是持有到初始內存值,這樣我可以取代它時,我做了測試特定內存位置的最佳方式?我相信註冊AX - DX已經在使用。

沒錯。你可以使用al存儲原始值,並在blcl01預裝,然後做這樣的事情(把我的頭頂部):

mov al, es:[di] // load/save original value 

mov es:[di], bl // store zero 
cmp bl, es:[di] // check that it sticks 
jne @pushbad // jump if it didn't 

mov es:[di], cl // same for 'one' 
cmp cl, es:[di] 
jne @pushbad 

mov es:[di], al // restore original value 
jmp @nextAddr 

@pushbad: 
mov es:[di], al // restore original value (may be redundant as the mem is bad) 
push es 
push di 

@nextAddr: 
... 
+0

我應該如同我爲DS和SS一樣初始化ES嗎?另外,我不熟悉DI。我可以在代碼中用DI替換每個BX嗎?這樣,DI將是我的內存偏移值而不是BX? – Ben 2014-10-08 01:37:23

+0

是的,在這種情況下,任何人都應該工作一樣。您可以方便地加載一個片段:偏移對與例如'les di' - 或者你可以單獨加載'es'寄存器。 'push <段值>''pop es''。 – 2014-10-08 01:41:25

0

有關也測試一些詞我們自己的例程聲明的內存位置。我們可以將我們的例程複製並運行到顯示設備的幀緩衝區中。

..

注意:如果我們想存儲或立即值進行比較的內存位置,然後我們必須指定我們要多少字節訪問。 (但與使用寄存器作爲源或目標相反,彙編程序已知道它的大小,所以我們不需要指定。)

訪問一個地址的一個字節(使用立即數值):

CMP BYTE[BX], 0  ; with NASM (Netwide Assembler) 
MOV BYTE[BX], 0 

CMP BYTE PTR[BX], 0 ; with MASM (Microsoft Macro Assembler) 
MOV BYTE PTR[BX], 0 

訪問兩個不會忽略的兩個字節一起
(執行速度更快,如果目標地址甚至排列):

CMP WORD[BX], 0  ; with NASM 
MOV WORD[BX], 0 

CMP WORD PTR[BX], 0 ; with MASM 
MOV WORD PTR[BX], 0 
0

如果你開始的假設,在RAM中的任何位置可能有缺陷;那麼這意味着您不能使用RAM來存儲您的代碼或數據。這包括臨時使用 - 例如,您不能將代碼臨時存儲在RAM中,然後將其複製到顯示內存中,因爲您可能會從RAM複製損壞的代碼以顯示內存。

記住這一點;唯一有意義的情況是ROM中的代碼測試RAM - 例如,在固件的POST(開機自檢)期間。此外;這意味着根本不能使用堆棧 - 不是用於跟蹤有故障的區域,甚至不用於調用函數/例程。

請注意,您可能會認爲您可以測試一個小區域(例如找到沒有錯誤的前1個KiB),然後使用該RAM來存儲結果等。這將是一個錯誤的假設。

對於RAM故障,有很多原因。第一組原因是地址總線或數據總線上的「斷開連接」和「短接」。舉一個簡單的例子,如果地址線12碰巧是開路的,最終的結果將是前4個KiB總是具有與第二個4 KiB RAM相同的內容。您可以儘可能多地測試內存的第一個4 KiB並確定它是「好的」,但是當測試第二個4 KiB的RAM時,會丟棄內存的前4 KB內容。

有一個「智能序列」的測試。具體來說,測試地址線從最高到最低(例如,將不同的值寫入0x000000和0x800000,並檢查它們是否都是正確的;然後對0x000000和0x400000執行相同的操作,然後執行0x000000和0x200000,依此類推,直到找到地址0x000000和0x000001)。然而,RAM芯片連接到CPU的方式並不像直接映射那麼簡單。例如,也許地址的最高位選擇哪一組RAM;在這種情況下,您必須同時測試0x000000和0x400000,並且還要測試兩個存儲區0x800000和0xC00000。

一旦確定地址線正常工作,那麼你可以做類似的數據線和RAM本身。最常見的測試稱爲「行走測試」;在那裏你存儲0x01,然後0x02,等等(最多0x80)。它檢測諸如「粘性位」之類的事物(例如,位的狀態恰好「卡住」其鄰居的狀態)。如果你只寫(例如)0x00並測試它然後寫0xFF並測試它,那麼你將錯過大多數RAM故障。

另外; 「打開連接」時要非常小心。在某些機器上,總線電容可以在你身上玩技巧,在那裏你寫一個值,總線電容「存儲」以前的值,這樣當你讀回時,即使沒有連接,它看起來也是正確的。爲了避免這種風險,您需要在兩者之間寫入不同的值 - 例如將0x55寫入正在測試的地址,然後在其他地方寫入0xAA,然後讀取原始值(並希望得到0x55,因爲RAM工作,而不是0xAA)。考慮到這一點(對於性能),您可能會考慮在RAM的一個區域執行「行走」,同時在下一個RAM區域執行「行走零」;所以你總是在從一個區域讀取一個值並從另一個區域讀取倒數值之間交替。

最後,一些內存問題取決於噪聲,溫度等。在這些情況下,您可以進行非常全面的內存測試,說它完全完美,然後在2分鐘後遭受RAM損壞。這就是爲什麼(例如)如果你真的想正確測試RAM,典型的建議是運行8小時左右的「memtest」。

+0

有趣,但有一點超出了我當前實驗室項目的範圍。謝謝。 – Ben 2014-10-10 17:51:50

相關問題