2014-10-08 3 views
2

Цель:
Мне нужно написать программу, которая проверяет функциональность записи всего 1 МБ памяти на основе байта по байтам для системы, использующей Микропроцессор Intel 80186. Другими словами, мне нужно записать от 0 до каждого байта в памяти, а затем проверить, действительно ли было написано 0. Затем мне нужно повторить процесс, используя значение 1. Наконец, любые ячейки памяти, у которых не было успешно записано 0 или 1, записанное в них во время их соответствующей операции записи, должны храниться в стеке.x86 Сборка: написание программы для проверки функциональности памяти для всего 1 МБ памяти

Обсуждение:
Я студентка по электротехнике в колледже (не компьютерная наука) и относительно новичок в ассемблере 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. Мне нужно определить наивысшее местоположение ОЗУ.

План:
1. В цикле: Write 0000H в ячейку памяти, Проверьте значение в этом месте ими памятью, PUSH значения ES и DI в стек, если проверка не удалась.
2. В цикле: записать FFFFH в ячейку памяти, проверить значение в этом месте памяти, PUSH значений ES и DI в стеке, если проверка завершилась неудачно.

Исходный код Исполнительное Предварительный план:

;**************************************************************************** 
;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, где вы можете сохранить эту область, которую вы тестируете? –

+0

Он отпустил вас с этой инструкцией? 'CMP CX, 10000h' –

+0

Во-первых, ни одна область не указана в отношении Req. 3. Во-вторых, я считаю, что «CMP CX, 10000H» разрешено. Есть ли причина, которой это не должно быть? – Ben

ответ

0

Как использовать ES: DI для обращения к области тестовой памяти?

E.g.mov al, es:[di]

Что является лучшим способом удержать к исходному значению памяти, так что я могу заменить его, когда я сделал тестирую конкретное место памяти? Я считаю, что регистры AX-DX уже используются.

Право. Вы можете использовать al для хранения исходного значения и имеют 0 и 1 предварительно загружены в bl и cl, а затем сделать что-то вроде этого (с верхней части моей головы):

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

Должен ли я инициализировать ES, как я сделал для DS и SS? Кроме того, я не знаком с DI. Могу ли я просто заменить каждый BX на DI в моем коде? Таким образом, DI будет моим значением смещения памяти вместо BX? – Ben

+0

Да, в этом контексте либо нужно работать одинаково. Вы можете удобно загрузить пару сегментов: смещение, например. 'les di' - или вы можете загрузить регистр' es' отдельно, например. 'push <значение сегмента>' 'pop es'. –

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

Если исходить из предположения, что любое место в оперативной памяти может быть неисправным; то это означает, что вы не можете использовать ОЗУ для хранения вашего кода или ваших данных. Это включает временное использование - например, вы не можете временно сохранить свой код в ОЗУ, а затем скопировать его, чтобы отобразить память, потому что вы рискуете скопировать поврежденный код из ОЗУ для отображения памяти.

С учетом этого; единственным случаем, когда это имеет смысл, является код в ПЗУ, тестирующий ОЗУ - например. во время прошивки микропрограммы (самотестирование при включении питания). Более того; это означает, что вы не можете использовать стек вообще - не для отслеживания дефектных областей или даже для вызова функций/подпрограмм.

Обратите внимание, что вы можете предположить, что вы можете протестировать небольшую область (например, найти первый 1 KiB, который не является неисправным), а затем использовать эту ОЗУ для хранения результатов и т. Д. Это было бы ложным предположением.

Для ошибок ОЗУ существует много причин. Первый набор причин - это «открытое соединение» и «короткое соединение» на адресной шине или шине данных. Для простого примера, если адресная строка 12 является разомкнутой цепью, конечный результат будет заключаться в том, что первые 4 KiB всегда имеют идентичное содержимое для второго 4 KiB ОЗУ. Вы можете протестировать первые 4 Кбайта ОЗУ столько, сколько хотите, и решить, что это «хорошо», но затем, когда вы тестируете второй 4 Кбайт ОЗУ, вы уничтожаете содержимое первых 4 Кбайт ОЗУ.

Существует «умная последовательность» тестов. В частности, проверьте адресные строки от наивысшего до самого низкого (например, напишите разные значения до 0x000000 и 0x800000 и убедитесь, что они оба правильные, а затем выполните то же самое для 0x000000 и 0x400000, затем 0x000000 и 0x200000 и т. Д., Пока не получите адреса 0x000000 и 0x000001). Однако, как микросхемы RAM подключены к ЦП, не обязательно так просто, как прямое отображение. Например, возможно, самый старший бит адреса выбирает, какой банк ОЗУ; и в этом случае вам придется тестировать как 0x000000, так и 0x400000, а также 0x800000 и 0xC00000 для тестирования обоих банков.

Как только вы уверены, что адресные строки работают; то вы можете сделать подобное для строк данных и самой ОЗУ. Самый распространенный тест называется «ходячим» тестом; где вы храните 0x01, затем 0x02 и т. д. (до 0x80). Это обнаруживает такие вещи, как «липкие биты» (например, когда состояние бит «застревает» в состоянии соседа). Если вы только пишете (например) 0x00 и протестируете его, напишите 0xFF и протестируйте его, после чего вы пропустите большинство ошибок RAM.

Также; будьте очень осторожны с «открытым соединением». На некоторых машинах емкость шины может воспроизводить трюки на вас, где вы пишете значение, а емкость шины «хранит» предыдущее значение, так что, когда вы читаете его обратно, похоже, что оно правильное, даже если соединение отсутствует. Чтобы избежать этого риска, вам нужно написать другое значение между ними - например. напишите 0x55 на адрес, который вы тестируете, затем напишите 0xAA в другом месте, затем прочитайте исходное значение назад (и надеемся, что вы получите 0x55, потому что RAM работает, а не 0xAA). Имея это в виду (для повышения производительности), вы можете подумать о том, чтобы делать «ходячие» в одной области ОЗУ, а также делать «ходящие нули» в следующей области ОЗУ; так что вы всегда чередуете между чтением значения из одной области и чтением инвертированного значения от другого.

И, наконец, некоторые проблемы с ОЗУ зависят от шума, температуры и т. Д. В этих случаях вы можете делать чрезвычайно тщательные проверки ОЗУ, скажем, что все это идеально, а затем через 2 минуты после этого повреждается ОЗУ. Вот почему (например) типичный совет - запустить что-то вроде «memtest» в течение 8 часов или около того, если вы действительно хотите правильно проверить RAM.

+0

Интересно, но немного вне сферы моего текущего проекта лаборатории. Благодарю. – Ben

Смежные вопросы