Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly MASM中的奇怪行为:“;十二月";指令导致减法2_Assembly_X86_Masm_Irvine32 - Fatal编程技术网

Assembly MASM中的奇怪行为:“;十二月";指令导致减法2

Assembly MASM中的奇怪行为:“;十二月";指令导致减法2,assembly,x86,masm,irvine32,Assembly,X86,Masm,Irvine32,我正在写一个程序来显示10秒的当前时间和日期。我被指示只能为此使用smallwin.inc。我编写了一个使用Irvine32.inc的程序,但是当我只切换到smallwin时,我需要编写一些输出数字的程序。当我添加这些时,一个非常奇怪的行为开始发生!我使用呼叫“dec repTime”,它将减少2而不是1!我尝试过“sub-repTime,1”,但它仍然如此!我甚至将repTime移到了eax,然后减去1,然后将eax移回repTime,它仍然减去2 我写的程序应该运行10秒。由于减法2的问题,

我正在写一个程序来显示10秒的当前时间和日期。我被指示只能为此使用smallwin.inc。我编写了一个使用Irvine32.inc的程序,但是当我只切换到smallwin时,我需要编写一些输出数字的程序。当我添加这些时,一个非常奇怪的行为开始发生!我使用呼叫“dec repTime”,它将减少2而不是1!我尝试过“sub-repTime,1”,但它仍然如此!我甚至将repTime移到了eax,然后减去1,然后将eax移回repTime,它仍然减去2

我写的程序应该运行10秒。由于减法2的问题,它将运行4秒!怎么了

这是我的密码:

; 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
;此代码演示如何使用Windows API函数来显示
; 当前日期和时间。它提供了一个运行的数字时钟,可以进行更新
; 10秒钟。从光标位置开始显示输出
; (5,5)并使用黄色前景和蓝色背景。
包括smallwin.inc
.数据
缓冲区数据库256重复(?)
提示字节“今天是:”;用于格式化输出的字符串
斜杠字节“/”
冒号字节“:”
空间字节“时间:”
换行词0D0Ah
雷普泰姆·德沃德10;显示时间为10秒
库斯波斯合作社;光标坐标
.数据?
超过德沃德;控制台输出句柄的存储
sysTimeNow系统时间;系统时间结构的存储
系统时间未来系统时间
.代码
写卡程序
pushfd
普沙德
mov缓冲器
调用WriteConsole、outHandle、偏移缓冲区、1、0、0
波帕德
popfd
ret
WriteChar ENDP
OUTIT PROC使用eax ebx ecx edx,
编号:SDWORD;方法参数
mov-ebx,10;基数系统的除数
异或ecx,ecx;数字计数器
cmp数为0;数字>=0吗?
jge-go;是-继续
负数;否定这个数字
mov al,'-'
调用WriteChar
去:
mov eax,编号
普迪吉特:
xor edx,edx
div-ebx;得到一位数
推动edx;保存它以供进一步处理
ecx公司;更新数字计数器
cmp-eax,0;处理结束
普迪吉特酒店
打印:
pop-eax;从堆栈中获取一个数字
或al,30h;ASCII转换
调用WriteChar;打印出来
循环打印
ret
远足
format2过程
本地零:字节
mov零,“0”
cmp-ax,10;数字<10?
jge L
推动eax;是-输出在0之前
调用WriteConsole、outHandle、ADDR zero、1、0、0
波普eax
L:调用outInt,eax;输出数字本身
ret
格式2 ENDP
主进程
调用GetStdHandle、STD\u输出\u句柄
mov输出手柄,eax;获取输出的控制台句柄
调用SetConsoleTextAttribute,outHandle,30;设置颜色
调用GetLocalTime,ADDR sysTimeFuture
;将未来时间设置为2013年12月25日
mov SYSTIMEFOUTURE.wDay,25
mov SYSTIMEFOUTURE.W月12日
mov SYSTIMEFOUTURE.wYear,2013年
mov SYSTIMEFURTURE.wHour,0
mov SYSTIMEFURTURE.wMinute,0
mov SYSTIMEFOUTURE.wSecond,0
阿贝尔:
调用SetConsoleUrsOrPosition、outHandle、cursPos
调用GetLocalTime,ADDR sysTimeNow;检索当前日期/时间
调用WriteConsole、outHandle、ADDR提示符、,
提示大小,0,0;输出提示
mov-eax,0
mov ax,sysTimeNow.wDay;月日
呼叫格式2
调用WriteConsole、outHandle、ADDR slash、1、0、0;输出'/'
mov ax,sysTimeNow.wMonth;月数
呼叫格式2
调用WriteConsole、outHandle、ADDR slash、1、0、0;输出'/'
mov-ax,sysTimeNow.wYear;打印年度
调用outInt,ax
调用WriteConsole、outHandle、ADDR space、SIZEOF space、0、0
mov ax,sysTimeNow.wHour;输出小时数
呼叫格式2
调用WriteConsole、outHandle、ADDR冒号、1、0、0;输出':'
mov ax,sysTimeNow.wMinute;输出分钟数
呼叫格式2
调用WriteConsole、outHandle、ADDR冒号、1、0、0;输出':'
mov ax,sysTimeNow.wssecond;输出秒数
呼叫格式2
调用睡眠,1000;等一秒钟
十二月份的时间;更新秒表计数器
阿贝尔
调用SetConsoleTextAttribute,outHandle,15;重新设置颜色
调用WriteConsole、outHandle、ADDR newLine、2、0、0;开行
调用ExitProcess,0
主端
端干管

查看outit的原型:

outInt PROTO number:SDWORD
所需参数为SDWORD-
SDWORD
,也可以是
DWORD
,无所谓,请查看作为参数传递的内容:

mov     ax, sysTimeNow.wYear                   ; print out the year
INVOKE  outInt, ax
您正在将一个
WORD
大小的寄存器作为参数传递,并在过程中使用
eax

将上述两行更改为:

movzx   eax, sysTimeNow.wYear                   ; print out the year
INVOKE  outInt, eax
或:


这将“调零”eax的上半部分并使其工作。或者,您可以做的是,让过程预期一个
WORD
大小的参数,因为这是您正在传递的参数,并在过程中使用
ax
而不是
eax

您是如何观察到这一点的?通过在调试器中单步执行代码..?不,如果运行该程序,它将只运行4秒钟。我在dec语句之后做了“INVOKE outit,repTime”,你可以看到每秒钟时钟上升1秒,repTime的值下降2。在减量前后放置INVOKE outit表明减量实际上只减少了1,但在再次到达语句之前,它是额外递减的。如果输出,递减,然后在循环中输出,预期的行为应该是一些输出,如“5,4,3,2,1”,w
xor     eax, eax
mov     ax, sysTimeNow.wYear                   ; print out the year
INVOKE  outInt, eax