查看完整版本: [組合語言] 讀出電腦現在有插幾條memory
頁: [1] 2

willy80720 發表於 2016-11-12 12:04 PM

[組合語言] 讀出電腦現在有插幾條memory

大家好

目前我想要做的事是能讀出電腦memory的資料 然後顯示出結果

只是當它讀完第一條memory然後顯示出來後

它就沒辦法再讀第二條

程式就掛在那邊沒辦法繼續了

所以想問說是哪裡有問題

我該如何改寫

謝謝

這是我改寫的code

.model small
.586
.stack 100h
.data
WELCOME_LINE DB 'Read Memorys','


CHANGE_LINE1 DB 10,13,'

;換行
CHANGE_LINE2 DB 10,13,'

;換行
SPACE DB 0,'


END_PROGRAM DB 'Type Enter to end the program','


SMBASE DW 0F040h; SMB_BASE address
MAX_LEN DB 3
ACT_LEN DB ?
BUFFER DB 3 dup(?)
TEMP DB 0
.code
start:
;initilization
mov ax,@data
mov ds,ax
;Print WELCOME_LINE
mov ah,09h
lea dx,WELCOME_LINE
int 21h
call changeLine1
xor cx,cx ;cx for counter
call CheckSmbusReady
call ReadSpdData1
call changeLine1
call ReadSpdData2
call changeLine1
;Print END_PROGRAM
mov ah,09h
lea dx,END_PROGRAM
int 21h
;
;mov ah,0ah
;lea dx,MAX_LEN
;int 21h
mov ax,4c00h ;return 0
int 21h
;==CheckSmbusReady==
CheckSmbusReady:
mov dx,SMBASE
in al,dx
mov ah,40h
cmp al,ah
jnz CheckSmbusReady
retn
;==CheckByteDoneStatus==
CheckByteDoneStatus:
mov dx,SMBASE
in al,dx
mov ah,42h
cmp al,ah
jnz CheckByteDoneStatus
retn
;==ReadSpdData1==
ReadSpdData1:
;set HST_STS
mov dx,SMBASE
mov al,0FFh
out dx,al
;set Slave Address
mov dx,SMBASE
add dX,04H
mov al,0A1h; for read SPD
out dx,al
;set HST_CMD to 00h
mov dx,SMBASE
add dX,03H
mov al,117
add al,cl
out dx,al
;set HST_D0 to 00h
mov dx,SMBASE
add dX,05H
mov al,00
out dx,al
;set HST_CNT 0x48 Byte Read
mov dx,SMBASE
add dx,02H
mov al,48h
out dx,al
call CheckByteDoneStatus
;print offset[]
mov dx,SMBASE
add dx,05h
in al,dx
mov TEMP,al
call hex2ascii
call printSpace
.if cl<=7
add cl,1
call ReadSpdData1
.elseif cl==8
call ChangeLine1
retn
.endif
retn
;==ReadSpdData2==
ReadSpdData2:
;set HST_STS
mov dx,SMBASE
mov al,0FFh
out dx,al
;set Slave Address
mov dx,SMBASE
add dX,04H
mov al,0A5h; for read SPD
out dx,al
;set HST_CMD to 00h
mov dx,SMBASE
add dX,03H
mov al,117
add al,cl
out dx,al
;set HST_D0 to 00h
mov dx,SMBASE
add dX,05H
mov al,00
out dx,al
;set HST_CNT 0x48 Byte Read
mov dx,SMBASE
add dx,02H
mov al,48h
out dx,al
call CheckByteDoneStatus
;print offset[]
mov dx,SMBASE
add dx,05h
in al,dx
mov TEMP,al
call hex2ascii
.if cl<=7
add cl,1
int 21h
.elseif cl==8
int 21h
retn
.endif
retn
;==hex2ascii===
hex2ascii:
xor ax,ax
mov al,TEMP
and al,0f0h
ror al,4
;.if al!=0
.if al>=00h && al <=09h
add al,30h ;add 30h,become ascii number
.else
add al,37h ;add 37h,become ascii alphabet
.endif
mov ah,02h
mov dl,al
int 21h
;.endif
mov al,TEMP
and al,0fh
.if al>=00h && al<=09h
add al,30h
.else
add al,37h
.endif
mov ah,02h
mov dl,al
int 21h
retn
;==changeLine1
changeLine1:
;Print CHANGE_LINE1
mov ah,09h
lea dx,CHANGE_LINE1
int 21h
retn
;==printSpace
printSpace:
mov ah,09h
lea dx,SPACE
int 21h
retn
;======end the program=========
end start

...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><div></div>

scottcheng 發表於 2016-11-12 11:49 PM

本帖最後由 scottcheng 於 2016-11-12 11:52 PM 編輯

(1) A1 應該是bank0 + read , A5 應該是bank 2 + read 是不是這個設錯了..
(2) mov al,117  
     add al,cl     <--- cl 哪來的值? 我的認知妳是你想讀 117 + 0 ~ 117+7 對吧, 所以才讀spd1 時, 會再 add cl, 1 , 如果是, 妳第二次並沒有把 cl 歸 0 , 妳再 readspd1 至少還有 xor cx,cx
(3) 妳已經透過SMBASE+03h 送出你要讀的reg, 為什麼還要送 SMBASE+05h ? 送 0 出去
(4) 146 行 妳不是應該再 call 一次 read spd2 ? 而不是 int 21h
(5) 148 行 你直接 call int 21h 我不清楚ah當時是甚麼, 你最好弄清楚, spd1 和 spd2 寫法不同

我大概就單純看code 的結論, 你思考一下吧!
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

willy80720 發表於 2016-11-13 09:13 AM

後來我是有一個想法是說
程式會掛在那邊可能是因為暫存器有存spd1的值在裡面
導致沒法繼續做spd2的事
所以想說如果把spd1印完後清掉空間再做spd2是不是就可以了

scottcheng 發表於 2016-11-14 03:05 AM

smbase 妳不是有填 ff 去 reset ? 我是不知道要不要做這個動作. 但很明顯, 我在 2f 寫的東西, 妳可以仔細看一看.. 光妳的程式寫法就兩套. 尤其3,4,5 這三點, 妳的code肯定有問題!

如果所講, 如果你覺得是因為 read spd1 有問題, 那你可以把 read spd1 先 mark 掉, 看注意妳在 call readspd1 之前有 xor cx, cx.. readsp2 並沒有..  

ps: 我已經10年沒寫bios, 所以我只能看code 的邏輯, 妳先更正我在2f提到的問題, 在試驗一次, 如果你懷疑 readspd1 有問題, 把他mark掉, 直接 call readsp2
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

willy80720 發表於 2016-11-14 01:57 PM

其實ReadSpdData1跟2是一樣的
只差在一個是mov al,0A1h 一個是0A5h
我有單獨拉只讀spd1跟2的
讀到有插卡的位置時就能正常顯示出資料
但是去讀沒有插卡的位置時 他就會掛在那邊 沒辦法繼續<br><br><br><br><br><div></div>

scottcheng 發表於 2016-11-14 06:34 PM

我是不知道你發生甚麼狀況. 但
102-106 和 144-148 明明就不一樣, 另外 145   cl 根本沒 初始化 . 你是從 8 開始
如果你還是覺得一模一樣, 那我也幫不上忙, 畢竟我沒你的環境, 也只能從你貼的code上去建議!

willy80720 發表於 2016-11-14 08:09 PM

本帖最後由 willy80720 於 2016-11-14 08:13 PM 編輯

謝謝你的指導我有修改過一些地方了  
那我現在改用的方式是 建兩個程式
改的地方就是76行的部分 1個是A1h 1個是A5h

那我自己也有跑過了 單獨個別跑這兩個程式 都沒問題
可是如果是依序跑的話(先跑A1的再跑A5的時候,或是先跑A5再跑A1的)
先執行的程式會正常顯示出我要的值 可是要接著跑下一個 程式就會掛在那邊

那現在的問題就卡在
為什麼沒辦法連續執行程式
          .model small
          .586
          .stack 100h
          .data
WELCOME_LINE DB 'Read Manufacture Data in Memory Spd in Memory Spd 75H to 7DH','


CHANGE_LINE DB 10,13,'

;??
SPACE DB 0,'


END_PROGRAM DB 'Type Enter to end the program','



SMBASE DW 0F040h; SMB_BASE address


MAX_LEN DB 3
ACT_LEN DB ?
BUFFER DB 3 dup(?)
TEMP DB 0


          .code
start:
          ;initilization
          mov ax,@data
          mov ds,ax
          ;Print WELCOME_LINE
          mov ah,09h
          lea dx,WELCOME_LINE
          int 21h
  call changeLine
  xor cx,cx ;cx for counter
  call CheckSmbusReady
  call ReadSpdData
  call changeLine
          ;Print END_PROGRAM
          mov ah,09h
          lea dx,END_PROGRAM
          int 21h
          ;
  ;mov ah,0ah
          ;lea dx,MAX_LEN
          ;int 21h
          mov ax,4c00h ;return 0
          int 21h
;==CheckSmbusReady==
CheckSmbusReady:
  mov dx,SMBASE
  in al,dx
  mov ah,40h
          cmp al,ah
          jnz CheckSmbusReady
  retn
;==CheckByteDoneStatus==
CheckByteDoneStatus:
  mov dx,SMBASE
  in al,dx
  mov ah,42h
  cmp al,ah
  jnz CheckByteDoneStatus
  retn
;==ReadSpdData==
ReadSpdData:
  ;set HST_STS
  mov dx,SMBASE
  mov al,0FFh
  out dx,al
  ;set Slave Address
  mov dx,SMBASE
  add dx,04H
  mov al,0A1h; for read SPD
  out dx,al
  ;set HST_CMD to 00h
  mov dx,SMBASE
  add dx,03H
  mov al,117
  add al,cl
  out dx,al
  ;set HST_D0 to 00h
  mov dx,SMBASE
  add dx,05H
  mov al,00
  out dx,al
  ;set HST_CNT 0x48 Byte Read
  mov dx,SMBASE
  add dx,02H
  mov al,48h
  out dx,al
  
  call CheckByteDoneStatus
  
  ;print offset[]
  mov dx,SMBASE
  add dx,05h
  in al,dx
  mov TEMP,al
      call hex2ascii
      call printSpace
      .if cl<=7
          add cl,1
          call ReadSpdData
      .elseif cl==8
          call ChangeLine
          retn
      .endif
  retn
;==hex2ascii===
hex2ascii:
      xor ax,ax
      mov al,TEMP
      and al,0f0h
      ror al,4
      ;.if al!=0
          .if al>=00h && al <=09h
          add al,30h ;add 30h,become ascii number
          .else
          add al,37h ;add 37h,become ascii alphabet
          .endif
          mov ah,02h
          mov dl,al
          int 21h
      ;.endif
      mov al,TEMP
      and al,0fh
      .if al>=00h && al<=09h
          add al,30h
      .else
          add al,37h
      .endif
      mov ah,02h
      mov dl,al
      int 21h
      retn
;==changeLine
changeLine:
      ;Print CHANGE_LINE
      mov ah,09h
      lea dx,CHANGE_LINE
      int 21h
      retn
;==printSpace
      printSpace:
      mov ah,09h
      lea dx,SPACE
      int 21h
      retn
;======end the program=========
      end start


...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

scottcheng 發表於 2016-11-15 12:25 PM

37-40 改成
; read spd1
call CheckSmbusReady  
mov cx, 0A100h
call ReadSpdData
call changeLine
; read spd2
call CheckSmbusReady  
mov cx, 0A500h
call ReadSpdData
call changeLine

76
mov al, ch; for read SPD

101 插入
push cx

104 插入
pop cx

試試看...call int21h 我不確定他會不會動到 cx

willy80720 發表於 2016-11-15 03:54 PM

目前試下來 第一個可以正常秀出結果
輪到第二個就掛在那邊 不會秀出結果

willy80720 發表於 2016-11-15 05:39 PM

本帖最後由 willy80720 於 2016-11-15 10:33 PM 編輯

剛剛我一行一行試 看是從哪裡開始會掛在那邊
然後在read spd2的call CheckSmbusReady
程式就會掛在那邊了 call changeLine
  ; read spd1
  call CheckSmbusReady  
  mov cx, 0A100h
  call ReadSpdData
  call changeLine
  ;xor cx,cx
  ; read spd2
  call CheckSmbusReady  
  mov cx, 0A500h
  call ReadSpdData
  call changeLine至於為什麼smbus要加那些數值
我只能說我是拿別人的程式來用
也跑出我要的結果 所以就直接來用了不過我有看你貼的網站
裡面倒是有提到加那些數值的原因
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div><br><br><br><br><br><div></div>

willy80720 發表於 2016-11-15 11:14 PM

其實簡單的來說就是我7樓的程式(讀A1h的程式)
如果連續重複執行兩次
第一次會正常顯示出值
第二次就會掛在那邊
我想解決為什麼會掛在那邊的原因

scottcheng 發表於 2016-11-16 03:12 AM

妳試看看, 如果在不行...沒實際環境, 妳給的條件只有停在那邊, 我也無法幫忙甚麼, 就這樣了
(1) 55-57  (理論只需要check host_busy , bit0)
  mov ah,40h
  cmp al,ah
  jnz CheckSmbusReady
改成
  test al, 01h
  jz CheckSmbusReady


(2) 63 -   (理論只需要check host_busy , bit0)
  mov ah,42h
  cmp al,ah
  jnz CheckByteDoneStatus
  
改成
test al, 01h
jz CheckByteDoneStatus

(3) remark 85-88 (我是認為不需要做這個動作)
  mov dx,SMBASE
  add dx,05H
  mov al,00
  out dx,al
...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

willy80720 發表於 2016-11-16 09:48 AM

scottcheng 發表於 2016-11-16 03:12 AM static/image/common/back.gif
妳試看看, 如果在不行...沒實際環境, 妳給的條件只有停在那邊, 我也無法幫忙甚麼, 就這樣了
(1) 55-57  (理 ...

你好 你說的實際環境是指甚麼?
我是在dos下執行我所build的exe檔

chevylin0802 發表於 2016-11-16 10:19 AM

本帖最後由 chevylin0802 於 2016-11-16 10:31 AM 編輯

純DOS環境指的是DOS開機的方式
不管你是用早期MSDOS的哪一個版本都算

另一種則稱之為DOS模擬環境
這種則是指在Windows的環境下開啟出來的DOS模擬器
或稱DOS指令環境

純DOS環境的話可以完全排除其它各種源自於多工環境所延申出來的問題
但是
如果是Windows下的DOS環境
那麼IN/OUT指令要很小心使用
因為隨時可能被系統岔斷給中斷執行
等到系統中斷處理程序完成之後
你的程式執行的環境已經變了

而且照道理來講你的程式應該是要編成.com的檔案
並讓它的code segment的offset固定在100H的位置上
因為exe是一種含有特定執行檔表頭的可執行檔
而且通常它的程式碼一開始是要針對記憶體管理模式進行設置
程式的啟始要先針對CPU的CS,DS,ES,SS以及BP, DI, SI等暫存器進行規劃的


一般來講像是在多工作業系統裏面進行這種處理
是需要先進行NMI處理的
也就是需要先進行中斷遮罩
等到I/O的存取完全完成之後再重新打開

針對記憶體的控制或者查詢的動作來講
更需要注意到的是DMA控制器的部份
因為它會干擾到記憶體控制器的暫存器狀態

另外更重要的是在於要對I/O進行控制的基本觀念在於需要了解硬體
尤其是關於控制晶片的時序圖方面的問題
所以在以前寫BIOS的程式設計師其實都已經有能力可以成為硬體工程師
因為軔體設計是要軟硬體兼備的知識
頻譜分析儀以及高頻示波器更是軔體工程師的標準配備
這也是純軟體的工程師所搞不定的主要原因

CPU的時脈現在普遍都在2.0GHz以上
但DDR RAM卻沒有那麼快
更不用談到其它PCI/PCIe裝置的時脈
也因此
通常CPU與CPU之外的周邊最起碼都會有三個控制腳位
分別是interrupt, RO, RW
只要時序圖沒有顧好的時候
軟體就會當機

也因此通常即使是在OS Kernel的部份
都會在I/O動作的過程當中進行一定時間的延遲(尤其是採取polling的方式時更需要長一點時間的delay)
比如10 nano seconds ~ 50 nano seconds
而且必定需要先進行中斷遮罩
以避免有其它的硬體中斷發生所產生的干擾

...<div class='locked'><em>瀏覽完整內容,請先 <a href='member.php?mod=register'>註冊</a> 或 <a href='javascript:;' onclick="lsSubmit()">登入會員</a></em></div>

willy80720 發表於 2016-11-16 09:45 PM

chevylin0802 發表於 2016-11-16 10:19 AM static/image/common/back.gif
純DOS環境指的是DOS開機的方式
不管你是用早期MSDOS的哪一個版本都算



那這樣我是該在哪裡加延遲的動作?<br><br><br><br><br><div></div>
頁: [1] 2