J'écris un programme pour afficher l'heure et la date actuelles pendant 10 secondes. Je suis dirigé que je peux utiliser UNIQUEMENT smallwin.inc pour cela. J'ai écrit un programme qui fonctionne en utilisant Irvine32.inc, mais quand je passe à Smallwin, je devais écrire quelques procédures pour la sortie des nombres. Quand j'ai ajouté ces derniers, un comportement TRÈS ÉTRANGE a commencé à se produire! J'utilise l'appel "dec repTime" et il diminuera de 2 au lieu de 1! J'ai essayé "sub repTime, 1" et il fait toujours la même chose! J'ai même déplacé repTime à eax, puis soustrait 1, puis déplacé eax à repTime, il soustrait toujours 2!Comportement étrange dans MASM: directive "dec" provoque la soustraction par 2
Le programme que j'ai écrit est supposé fonctionner pendant 10 secondes. En raison du problème de soustraction 2, il fonctionne pendant 4 secondes à la place! Qu'est-ce qui ne va pas?!?
Voici mon code:
; this code demonstrates the usage of Windows API functions to display
; current date and time. It provides a running digital clock that updates
; itself for 10 seconds. The output is displayed starting with cursor position
; (5,5) and uses yellow foreground and blue background.
INCLUDE smallwin.inc
.data
buffer DB 256 DUP(?)
prompt BYTE "Today is: " ; strings used to format the output
slash BYTE '/'
colon BYTE ':'
space BYTE " Time: "
newLine WORD 0D0Ah
repTime DWORD 10 ; display time for 10 seconds
cursPos COORD <5,5> ; cursor coordinates
.data?
outHandle DWORD ? ; storage for console output handle
sysTimeNow SYSTEMTIME <> ; storage for system time structure
sysTimeFuture SYSTEMTIME <>
.code
WriteChar PROC
pushfd
pushad
mov buffer,al
INVOKE WriteConsole, outHandle, OFFSET buffer, 1, 0, 0
popad
popfd
ret
WriteChar ENDP
outInt PROC USES eax ebx ecx edx,
number: SDWORD ; method parameter
mov ebx, 10 ; divisor for the radix system
xor ecx, ecx ; digits counter
cmp number, 0 ; is number >= 0?
jge go ; yes - proceed
neg number ; negate the number
mov al, '-'
INVOKE WriteChar
go:
mov eax, number
puDigit:
xor edx, edx
div ebx ; get one digit
push edx ; save it for further processing
inc ecx ; update the digits counter
cmp eax, 0 ; end of processing
jne puDigit
printIT:
pop eax ; get a digit from stack
or al, 30h ; ASCII conversion
INVOKE WriteChar ; print it
loop printIT
ret
outInt ENDP
format2 PROC
LOCAL zero:BYTE
mov zero, '0'
cmp ax, 10 ; number < 10 ?
jge L
push eax ; YES - output preceeding 0
INVOKE WriteConsole, outHandle, ADDR zero, 1, 0, 0
pop eax
L: INVOKE outInt, eax ; output the number itself
ret
format2 ENDP
main PROC
INVOKE GetStdHandle, STD_OUTPUT_HANDLE
mov outHandle, eax ; get console handle for output
INVOKE SetConsoleTextAttribute, outHandle, 30 ; setup colors
INVOKE GetLocalTime, ADDR sysTimeFuture
;set Future Time to Dec 25, 2013
mov sysTimeFuture.wDay, 25
mov sysTimeFuture.wMonth, 12
mov sysTimeFuture.wYear, 2013
mov sysTimeFuture.wHour, 0
mov sysTimeFuture.wMinute, 0
mov sysTimeFuture.wSecond, 0
startLabel:
INVOKE SetConsoleCursorPosition, outHandle, cursPos
INVOKE GetLocalTime, ADDR sysTimeNow ; retrieve current date/time
INVOKE WriteConsole, outHandle, ADDR prompt,
SIZEOF prompt, 0, 0 ; output prompt
mov eax, 0
mov ax, sysTimeNow.wDay ; day of the month
call format2
INVOKE WriteConsole, outHandle, ADDR slash, 1, 0, 0 ; output '/'
mov ax, sysTimeNow.wMonth ; month number
call format2
INVOKE WriteConsole, outHandle, ADDR slash, 1, 0, 0 ; output '/'
mov ax, sysTimeNow.wYear ; print out the year
INVOKE outInt, ax
INVOKE WriteConsole, outHandle, ADDR space, SIZEOF space, 0, 0
mov ax, sysTimeNow.wHour ; output hours
call format2
INVOKE WriteConsole, outHandle, ADDR colon, 1, 0, 0 ; output ':'
mov ax, sysTimeNow.wMinute ; output minutes
call format2
INVOKE WriteConsole, outHandle, ADDR colon, 1, 0, 0 ; output ':'
mov ax, sysTimeNow.wSecond ; output seconds
call format2
INVOKE Sleep, 1000 ; wait for 1 second
dec repTime ; update the stop watch counter
jnz startLabel
INVOKE SetConsoleTextAttribute, outHandle, 15 ; reset the colors
INVOKE WriteConsole, outHandle, ADDR newLine, 2, 0, 0 ; start new line
INVOKE ExitProcess, 0
main ENDP
END main
Comment avez-vous observé cela? En passant par le code dans un débogueur ..? – Michael
Non, si vous exécutez le programme, il ne fonctionnera que pendant 4 secondes. J'ai fait "INVOKE outInt, repTime" après l'instruction dec, et vous pouvez voir chaque seconde que l'horloge monte d'une seconde et la valeur de repTime diminue de 2. – Drifter64
En plaçant une invocation outInt avant et après le décrément montre que le En fait, la diminution ne diminue que de 1, mais d'une manière ou d'une autre, avant que l'instruction soit à nouveau atteinte, elle est décrémentée EXTRA. Si vous produisez, décrémentez, puis produisez dans une boucle, le comportement attendu devrait être une sortie comme "5,4 4,3 3,2 2,1", où les espaces séparent chaque boucle, cependant, la sortie est en fait "5, 4 3,2 1,0 "ce qui signifie que la décrémentation fonctionne correctement, mais en quelque sorte cette adresse de mémoire est en train d'être foiré ailleurs! – Drifter64