如何在年龄计算程序中使用 MASM 汇编语言中的条件语句?
How to use conditional statements in MASM Assembly Language for an age calculating program?
我目前正在上大学汇编语言课程,给我的家庭作业是编写一个程序,其中可以使用出生年月日来 return 年龄. (当前的年月日在程序的早期定义。)
程序的主要部分是条件 if 语句,将输入的年份与当前年份、输入的月份与当前月份以及输入的日期与当前日期进行比较。
还考虑了一些特殊情况,例如输入未来的日期,或输入与当前年份相同的年份,或者即使您输入的日期与当前日期相同将在输出末尾添加“生日快乐”文本的当前日期。
想要的 input/output 将是:
Enter the year of your birth: **2002**
Enter the month of your birth: **4**
You are 19 years old
我得到的input/output是这样的:
Enter the year of your birth: **2002**
Enter the month of your birth: **4**
You are 4294965279 years old
我很确定我搞砸了我对 EAX 和 DWORD 的使用,但我并不肯定。
我在这个问题中包含了整个程序,以便您更好地理解我想要实现的目标。
任何有关我搞砸的地方的提示将不胜感激。
此外,请记住,这只是我在此 class 中的第三次作业,所以不要指望我知道任何高级 MASM 汇编语言术语或技术。
这是代码(为了方便起见,伪代码在右边):
TITLE H03C (H03C.asm)
; William Sanacore
; 9/23/2021
; H03C
; Description: Write a program that calculates how old you are.
INCLUDE Irvine32.inc
.data
curYear DWORD ?
curMonth DWORD ?
curDay DWORD ?
yearMsg BYTE "Enter the year of your birth: ", 0
montMsg BYTE "Enter the month of your birth: ", 0
dayMsg BYTE "Enter the day of your birth: ", 0
lessyearMsg BYTE "You are less than one year old"
youAreMsg BYTE "You are ", 0
yearsOldMsg BYTE " years old", 0
yearsOldHBMsg BYTE " years old, Happy Birthday", 0
notBornMsg BYTE "You have not been born yet", 0
year DWORD ?
month DWORD ?
day DWORD ?
age DWORD ?
.code
main PROC ; Start
mov curYear, 2021 ; curYear = 2021
mov curMonth, 9 ; curMonth = 9
mov curDay, 23 ; curDay = 23
LEA EDX, yearMsg ; Print "Enter the year of your birth: "
call WriteString
call ReadDec ; Input year
mov year, DWORD
mov year, EAX ; IF year = curYear THEN
cmp EAX, curYear
jne ELSE1
LEA EDX, lessyearMsg ; Print "you are less than 1 year old"
call WriteString
jmp ENDIF1
ELSE1: ; ELSE
mov year, EAX ; IF year < curYear THEN
cmp EAX, curYear
jnl ELSE2
LEA EDX, montMsg ; Print "Enter the month of your birth: "
call WriteString
call ReadDec ; Input month
mov month, DWORD
mov year, EAX ; age = curYear - year
sub EAX, curYear
mov age, DWORD
mov month, EAX ; IF month > curMonth THEN
cmp EAX, curMonth
jng ELSE3
mov age, EAX ; age = age - 1
sub EAX, '1'
mov age, DWORD
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF2
ELSE3: ; ELSE
mov month, EAX ; IF month < curMonth THEN
cmp EAX, curMonth
jnl ELSE4
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF3
ELSE4: ; ELSE
LEA EDX, dayMsg ; Print "Enter day of your birth: "
call WriteString
call ReadDec ; Input day
mov day, DWORD
mov day, EAX ; IF day > curDay THEN
cmp EAX, curDay
jng ELSE5
mov age, EAX ; age = age - 1
sub EAX, '1'
mov age, DWORD
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF4
ELSE5: ; ELSE
mov day, EAX ; IF day < curDay THEN
cmp EAX, curDay
jnl ELSE6
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF5
ELSE6: ; ELSE
LEA EDX, youAreMsg ; Print "you are "; age; " years old, Happy Birthday"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF6
ENDIF6: ; ENDIF
call CRLF
exit
ENDIF5: ; ENDIF
call CRLF
exit
ENDIF4: ; ENDIF
call CRLF
exit
ENDIF3: ; ENDIF
call CRLF
exit
ELSE2: ; ELSE
LEA EDX, notBornMsg ; Print "you haven't been born yet"
call WriteString
ENDIF2: ; ENDIF
call CRLF
exit
ENDIF1: ; ENDIF
call CRLF
exit ; Stop
main ENDP
END main
You are 4294965279 years old
恭喜!请告诉我们您是如何应对的...
开个玩笑,代码有很多问题。下面列出了几个:
call ReadDec ; Input year
mov year, DWORD
mov year, EAX ; IF year = curYear THEN
cmp EAX, curYear
ReadDec 的结果在 EAX
寄存器中。 mov year, DWORD
指令没有意义!如果您写评论,请将它们放在它们所属的行上。
call ReadDec ; Input year
mov year, eax
cmp eax, curYear ; IF year = curYear THEN
call ReadDec ; Input month
mov month, DWORD
mov year, EAX ; age = curYear - year
sub EAX, curYear
mov age, DWORD
在您刚刚输入 月 的这部分代码中,您用这个 [= 破坏了已经建立的 年 22=] 指令!此代码还执行虚假计算“month - curYear”。
mov month, EAX ; IF month > curMonth THEN
cmp EAX, curMonth
目标是第一个操作数,源是第二个操作数。从 month 变量加载 EAX
寄存器需要:mov eax, month
.
mov age, EAX ; age = age - 1
sub EAX, '1'
mov age, DWORD
三行,三个错误。左边是目的地,右边是源头。值“1”是 49,但您只需要 1。'DWORD' 本身没有任何意义。
mov eax, age ; Load from memory
sub eax, 1 ; Decrement
mov age, eax ; Store to memory
一个较短的版本是:dec age
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF6
最后的“生日快乐”部分忘记实际引用相关消息。
mov edx, OFFSET yearsOldHBMsg
call WriteString
jmp ENDIF6
总而言之,代码很难读,你重复了好几遍。也许是不同的方法?
这是 BASIC 中的程序。
Print "Enter the year of your birth: "
Input year
IF year = curYear THEN
Print "you are less than 1 year old"
ELSE
IF year < curYear THEN
Print "Enter the month of your birth: "
Input month
age = curYear - year
IF month > curMonth THEN
age = age - 1
Print "you are "; age; " years old"
ELSE
IF month < curMonth THEN
Print "you are "; age; " years old"
ELSE
Print "Enter day of your birth: "
Input day
IF day > curDay THEN
age = age - 1
Print "you are "; age; " years old"
ELSE
IF day < curDay THEN
Print "you are "; age; " years old"
ELSE
Print "you are "; age; " years old, Happy Birthday"
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
Print "you haven't been born yet"
ENDIF
ENDIF
您正在尝试非常紧密地遵循 BASIC 代码,可能太紧密了!更好的策略是研究高级示例,找出其意图,然后尽可能高效地用汇编代码编写代码。下面是一个例子 'avoids advanced MASM assembly language terms or techniques':
mov curYear, 2021 ; curYear = 2021
mov curMonth, 9 ; curMonth = 9
mov curDay, 23 ; curDay = 23
mov edx, OFFSET yearMsg ; Print "Enter the year of your birth: "
call WriteString
call ReadDec ; Input year
mov ecx, curYear ; age = curYear - year
sub ecx, eax ; (*)
mov age, ecx
mov edx, OFFSET lessyearMsg ; "you are less than 1 year old"
jz finalMsg
mov edx, OFFSET notBornMsg ; "you haven't been born yet"
js finalMsg
mov esi, OFFSET yearsOldMsg
mov edx, OFFSET montMsg ; Print "Enter the month of your birth: "
call WriteString
call ReadDec ; Input month
mov month, eax
cmp eax, curMonth
jne maybeDec
mov edx, OFFSET dayMsg ; Print "Enter day of your birth: "
call WriteString
call ReadDec ; Input day
mov day, eax
cmp eax, curDay
jne maybeDec
mov esi, OFFSET yearsOldHBMsg ; " years old, Happy Birthday"
jmp fullMsg
maybeDec:
jb fullMsg ; (**)
dec age ; age = age - 1
fullMsg:
mov edx, OFFSET youAreMsg ; " you are"
call WriteString
mov eax, age
call WriteDec
mov edx, esi ; ESI={yearsOldMsg, yearsOldHBMsg}
finalMsg:
call WriteString
call CRLF
() 那些 mov <reg>, OFFSET <label>
指令比 lea <reg>, <label>
指令短一个字节。
(*) 无论如何都需要 age 计算。我们可以使用 SUB
指令的标志结果,而不是执行多个单独的 CMP
。
(**) 请注意,我确实使用了 unsigned 操作。天和月是无符号数。
我目前正在上大学汇编语言课程,给我的家庭作业是编写一个程序,其中可以使用出生年月日来 return 年龄. (当前的年月日在程序的早期定义。)
程序的主要部分是条件 if 语句,将输入的年份与当前年份、输入的月份与当前月份以及输入的日期与当前日期进行比较。
还考虑了一些特殊情况,例如输入未来的日期,或输入与当前年份相同的年份,或者即使您输入的日期与当前日期相同将在输出末尾添加“生日快乐”文本的当前日期。
想要的 input/output 将是:
Enter the year of your birth: **2002**
Enter the month of your birth: **4**
You are 19 years old
我得到的input/output是这样的:
Enter the year of your birth: **2002**
Enter the month of your birth: **4**
You are 4294965279 years old
我很确定我搞砸了我对 EAX 和 DWORD 的使用,但我并不肯定。
我在这个问题中包含了整个程序,以便您更好地理解我想要实现的目标。
任何有关我搞砸的地方的提示将不胜感激。
此外,请记住,这只是我在此 class 中的第三次作业,所以不要指望我知道任何高级 MASM 汇编语言术语或技术。
这是代码(为了方便起见,伪代码在右边):
TITLE H03C (H03C.asm)
; William Sanacore
; 9/23/2021
; H03C
; Description: Write a program that calculates how old you are.
INCLUDE Irvine32.inc
.data
curYear DWORD ?
curMonth DWORD ?
curDay DWORD ?
yearMsg BYTE "Enter the year of your birth: ", 0
montMsg BYTE "Enter the month of your birth: ", 0
dayMsg BYTE "Enter the day of your birth: ", 0
lessyearMsg BYTE "You are less than one year old"
youAreMsg BYTE "You are ", 0
yearsOldMsg BYTE " years old", 0
yearsOldHBMsg BYTE " years old, Happy Birthday", 0
notBornMsg BYTE "You have not been born yet", 0
year DWORD ?
month DWORD ?
day DWORD ?
age DWORD ?
.code
main PROC ; Start
mov curYear, 2021 ; curYear = 2021
mov curMonth, 9 ; curMonth = 9
mov curDay, 23 ; curDay = 23
LEA EDX, yearMsg ; Print "Enter the year of your birth: "
call WriteString
call ReadDec ; Input year
mov year, DWORD
mov year, EAX ; IF year = curYear THEN
cmp EAX, curYear
jne ELSE1
LEA EDX, lessyearMsg ; Print "you are less than 1 year old"
call WriteString
jmp ENDIF1
ELSE1: ; ELSE
mov year, EAX ; IF year < curYear THEN
cmp EAX, curYear
jnl ELSE2
LEA EDX, montMsg ; Print "Enter the month of your birth: "
call WriteString
call ReadDec ; Input month
mov month, DWORD
mov year, EAX ; age = curYear - year
sub EAX, curYear
mov age, DWORD
mov month, EAX ; IF month > curMonth THEN
cmp EAX, curMonth
jng ELSE3
mov age, EAX ; age = age - 1
sub EAX, '1'
mov age, DWORD
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF2
ELSE3: ; ELSE
mov month, EAX ; IF month < curMonth THEN
cmp EAX, curMonth
jnl ELSE4
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF3
ELSE4: ; ELSE
LEA EDX, dayMsg ; Print "Enter day of your birth: "
call WriteString
call ReadDec ; Input day
mov day, DWORD
mov day, EAX ; IF day > curDay THEN
cmp EAX, curDay
jng ELSE5
mov age, EAX ; age = age - 1
sub EAX, '1'
mov age, DWORD
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF4
ELSE5: ; ELSE
mov day, EAX ; IF day < curDay THEN
cmp EAX, curDay
jnl ELSE6
LEA EDX, youAreMsg ; Print "you are "; age; " years old"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF5
ELSE6: ; ELSE
LEA EDX, youAreMsg ; Print "you are "; age; " years old, Happy Birthday"
call WriteString
mov age, EAX
call WriteDec
LEA EDX, yearsOldMsg
call WriteString
jmp ENDIF6
ENDIF6: ; ENDIF
call CRLF
exit
ENDIF5: ; ENDIF
call CRLF
exit
ENDIF4: ; ENDIF
call CRLF
exit
ENDIF3: ; ENDIF
call CRLF
exit
ELSE2: ; ELSE
LEA EDX, notBornMsg ; Print "you haven't been born yet"
call WriteString
ENDIF2: ; ENDIF
call CRLF
exit
ENDIF1: ; ENDIF
call CRLF
exit ; Stop
main ENDP
END main
You are 4294965279 years old
恭喜!请告诉我们您是如何应对的...
开个玩笑,代码有很多问题。下面列出了几个:
call ReadDec ; Input year mov year, DWORD mov year, EAX ; IF year = curYear THEN cmp EAX, curYear
ReadDec 的结果在 EAX
寄存器中。 mov year, DWORD
指令没有意义!如果您写评论,请将它们放在它们所属的行上。
call ReadDec ; Input year
mov year, eax
cmp eax, curYear ; IF year = curYear THEN
call ReadDec ; Input month mov month, DWORD mov year, EAX ; age = curYear - year sub EAX, curYear mov age, DWORD
在您刚刚输入 月 的这部分代码中,您用这个 [= 破坏了已经建立的 年 22=] 指令!此代码还执行虚假计算“month - curYear”。
mov month, EAX ; IF month > curMonth THEN cmp EAX, curMonth
目标是第一个操作数,源是第二个操作数。从 month 变量加载 EAX
寄存器需要:mov eax, month
.
mov age, EAX ; age = age - 1 sub EAX, '1' mov age, DWORD
三行,三个错误。左边是目的地,右边是源头。值“1”是 49,但您只需要 1。'DWORD' 本身没有任何意义。
mov eax, age ; Load from memory
sub eax, 1 ; Decrement
mov age, eax ; Store to memory
一个较短的版本是:dec age
LEA EDX, yearsOldMsg call WriteString jmp ENDIF6
最后的“生日快乐”部分忘记实际引用相关消息。
mov edx, OFFSET yearsOldHBMsg
call WriteString
jmp ENDIF6
总而言之,代码很难读,你重复了好几遍。也许是不同的方法?
这是 BASIC 中的程序。
Print "Enter the year of your birth: "
Input year
IF year = curYear THEN
Print "you are less than 1 year old"
ELSE
IF year < curYear THEN
Print "Enter the month of your birth: "
Input month
age = curYear - year
IF month > curMonth THEN
age = age - 1
Print "you are "; age; " years old"
ELSE
IF month < curMonth THEN
Print "you are "; age; " years old"
ELSE
Print "Enter day of your birth: "
Input day
IF day > curDay THEN
age = age - 1
Print "you are "; age; " years old"
ELSE
IF day < curDay THEN
Print "you are "; age; " years old"
ELSE
Print "you are "; age; " years old, Happy Birthday"
ENDIF
ENDIF
ENDIF
ENDIF
ELSE
Print "you haven't been born yet"
ENDIF
ENDIF
您正在尝试非常紧密地遵循 BASIC 代码,可能太紧密了!更好的策略是研究高级示例,找出其意图,然后尽可能高效地用汇编代码编写代码。下面是一个例子 'avoids advanced MASM assembly language terms or techniques':
mov curYear, 2021 ; curYear = 2021
mov curMonth, 9 ; curMonth = 9
mov curDay, 23 ; curDay = 23
mov edx, OFFSET yearMsg ; Print "Enter the year of your birth: "
call WriteString
call ReadDec ; Input year
mov ecx, curYear ; age = curYear - year
sub ecx, eax ; (*)
mov age, ecx
mov edx, OFFSET lessyearMsg ; "you are less than 1 year old"
jz finalMsg
mov edx, OFFSET notBornMsg ; "you haven't been born yet"
js finalMsg
mov esi, OFFSET yearsOldMsg
mov edx, OFFSET montMsg ; Print "Enter the month of your birth: "
call WriteString
call ReadDec ; Input month
mov month, eax
cmp eax, curMonth
jne maybeDec
mov edx, OFFSET dayMsg ; Print "Enter day of your birth: "
call WriteString
call ReadDec ; Input day
mov day, eax
cmp eax, curDay
jne maybeDec
mov esi, OFFSET yearsOldHBMsg ; " years old, Happy Birthday"
jmp fullMsg
maybeDec:
jb fullMsg ; (**)
dec age ; age = age - 1
fullMsg:
mov edx, OFFSET youAreMsg ; " you are"
call WriteString
mov eax, age
call WriteDec
mov edx, esi ; ESI={yearsOldMsg, yearsOldHBMsg}
finalMsg:
call WriteString
call CRLF
() 那些 mov <reg>, OFFSET <label>
指令比 lea <reg>, <label>
指令短一个字节。
(*) 无论如何都需要 age 计算。我们可以使用 SUB
指令的标志结果,而不是执行多个单独的 CMP
。
(**) 请注意,我确实使用了 unsigned 操作。天和月是无符号数。