Masm64:学生通讯录

以下是一个简单的Masm64学生通讯录的示例代码,它可以实现添加、删除、查找和显示学生信息的功能。

一、数据结构定义

1. 学生信息结构

定义一个STUDENT结构来存储学生的信息,包括姓名(name)、年龄(age)和电话号码(phone_number)。每个字段的大小根据实际需求确定,这里姓名假设最大长度为30个字符(使用字节数组存储),年龄为2个字节(16位整数),电话号码为11个字符(也是字节数组)。

STUDENT STRUCT
    name BYTE 30 DUP(?)
    age WORD?
    phone_number BYTE 11 DUP(?)
STUDENT ENDS

2. 通讯录数组和计数器

定义一个数组来存储多个学生的信息,这里假设最多存储100个学生信息,使用students数组来表示。同时,定义一个计数器student_count来记录当前存储的学生数量。

students STUDENT 100 DUP(?)
student_count DWORD 0

二、显示菜单函数

1. display_menu函数

这个函数用于显示通讯录的操作菜单,让用户选择要执行的操作,如添加学生信息、删除学生信息、查找学生信息、显示所有学生信息或退出程序。

display_menu PROC
    mov edx, OFFSET menu_text
    call write_string ; 显示菜单文本
    call read_char ; 读取用户输入的字符
    ret
display_menu ENDP
menu_text  BYTE "1. Add Student", 13, 10
            BYTE "2. Delete Student", 13, 10
            BYTE "3. Find Student", 13, 10
            BYTE "4. Display All Students", 13, 10
            BYTE "5. Exit", 13, 10, 0

三、输入学生信息函数

1. input_student_info函数

该函数用于提示用户输入学生的姓名、年龄和电话号码,并将用户输入的数据存储到STUDENT结构中。在输入姓名和电话号码时,使用循环逐个字符读取,确保输入的字符串不超过定义的最大长度。对于年龄,使用read_word函数读取一个16位整数。

input_student_info PROC
    ; 输入姓名
    mov edx, OFFSET name_prompt
    call write_string
    mov ecx, 30
    mov esi, OFFSET students[student_count].name
    input_name_loop:
        call read_char
        cmp al, 13 ; 如果是回车键,结束输入
        je input_name_end
        mov [esi], al
        inc esi
    loop input_name_loop
    input_name_end:
    mov byte ptr [esi], 0 ; 添加字符串结束标志
    ; 输入年龄
    mov edx, OFFSET age_prompt
    call write_string
    call read_word
    mov students[student_count].age, ax
    ; 输入电话号码
    mov edx, OFFSET phone_prompt
    call write_string
    mov ecx, 11
    mov esi, OFFSET students[student_count].phone_number
    input_phone_loop:
        call read_char
        cmp al, 13 ; 如果是回车键,结束输入
        je input_phone_end
        mov [esi], al
        inc esi
    loop input_phone_loop
    input_phone_end:
    mov byte ptr [esi], 0 ; 添加字符串结束标志
    ret
input_student_info ENDP
name_prompt   BYTE "Enter student name: ", 0
age_prompt   BYTE "Enter student age: ", 0
phone_prompt BYTE "Enter student phone number: ", 0

四、添加学生信息函数

1. add_student函数

首先检查通讯录数组是否已满(即student_count是否达到了最大容量100)。如果未满,则调用input_student_info函数获取学生信息,并将其存储到数组中,然后递增student_count以更新学生数量。

add_student PROC
    cmp student_count, 100
    jae add_student_full ; 如果数组已满,跳转到提示信息
    call input_student_info
    inc student_count
    jmp add_student_end
    add_student_full:
    mov edx, OFFSET full_text
    call write_string
    add_student_end:
    ret
add_student ENDP
full_text BYTE "The student list is full.", 13, 10, 0

五、查找学生信息函数

1. find_student函数

该函数用于根据用户输入的姓名在通讯录中查找学生信息。它遍历students数组,逐个比较学生的姓名与用户输入的查找姓名。如果找到匹配的学生,显示该学生的详细信息;如果没有找到,显示相应的提示信息。

find_student PROC
    ; 获取要查找的学生姓名
    mov edx, OFFSET find_name_prompt
    call write_string
    mov ecx, 30
    mov esi, OFFSET find_name_buffer
    input_find_name_loop:
        call read_char
        cmp al, 13 ; 如果是回车键,结束输入
        je input_find_name_end
        mov [esi], al
        inc esi
    loop input_find_name_loop
    input_find_name_end:
    mov byte ptr [esi], 0 ; 添加字符串结束标志
    mov edi, 0
    find_student_loop:
    mov esi, OFFSET students[edi]
    mov ecx, 30
    repe cmpsb ; 比较姓名字符串
    jz student_found ; 如果找到匹配的学生,跳转到显示信息
    add edi, TYPE STUDENT ; 移动到下一个学生记录
    cmp edi, student_count * TYPE STUDENT ; 检查是否遍历完所有学生
    jb find_student_loop
    ; 如果没有找到学生
    mov edx, OFFSET not_found_text
    call write_string
    jmp find_student_end
    student_found:
    ; 显示找到的学生信息
    mov esi, OFFSET students[edi]
    mov edx, OFFSET student_info_text
    call write_string
    mov edx, esi
    add edx, OFFSET STUDENT.name
    call write_string
    mov edx, OFFSET age_info_text
    call write_string
    mov ax, students[edi].age
    call write_word
    mov edx, OFFSET phone_info_text
    call write_string
    mov edx, esi
    add edx, OFFSET STUDENT.phone_number
    call write_string
    find_student_end:
ret
find_student ENDP
find_name_prompt  BYTE "Enter the student name to find: ", 0
find_name_buffer  BYTE 30 DUP(?)
not_found_text    BYTE "Student not found.", 13, 10, 0
student_info_text BYTE "Student Information:", 13, 10, 0
age_info_text     BYTE "Age: ", 0
phone_info_text   BYTE "Phone Number: ", 0

六、删除学生信息函数

1. delete_student函数

该函数用于根据用户输入的姓名删除通讯录中的学生信息。首先查找要删除的学生,如果找到,则将该学生之后的所有学生信息向前移动一位,覆盖要删除的学生信息,并递减student_count。如果没有找到要删除的学生,显示相应的提示信息。

delete_student PROC
    ; 获取要删除的学生姓名
    mov edx, OFFSET delete_name_prompt
    call write_string
    mov ecx, 30
    mov esi, OFFSET delete_name_buffer
    input_delete_name_loop:
        call read_char
        cmp al, 13 ; 如果是回车键,结束输入
        je input_delete_name_end
        mov [esi], al
        inc esi
    loop input_delete_name_loop
    input_delete_name_end:
    mov byte ptr [esi], 0 ; 添加字符串结束标志
    mov edi, 0
    delete_student_loop:
    mov esi, OFFSET students[edi]
    mov ecx, 30
    repe cmpsb ; 比较姓名字符串
    jz student_found_to_delete ; 如果找到匹配的学生,跳转到删除操作
    add edi, TYPE STUDENT ; 移动到下一个学生记录
    cmp edi, student_count * TYPE STUDENT ; 检查是否遍历完所有学生
    jb delete_student_loop
    ; 如果没有找到学生
    mov edx, OFFSET not_found_text
    call write_string
    jmp delete_student_end
    student_found_to_delete:
    ; 执行删除操作,将后面的学生信息向前移动
    mov ecx, student_count
    dec ecx
    sub ecx, edi
    mov esi, edi
    add esi, TYPE STUDENT
    rep movsb
    dec student_count ; 更新学生数量
    mov edx, OFFSET deleted_text
    call write_string
    delete_student_end:
ret
delete_student ENDP
delete_name_prompt BYTE "Enter the student name to delete: ", 0
delete_name_buffer BYTE 30 DUP(?)
deleted_text       BYTE "Student deleted successfully.", 13, 10, 0

七、显示所有学生信息函数

1. display_all_students函数

该函数用于遍历students数组,逐个显示所有学生的信息。如果student_count为0,表示通讯录为空,显示相应的提示信息。

display_all_students PROC
    cmp student_count, 0
    je all_students_empty
    mov edi, 0
    display_students_loop:
    mov esi, OFFSET students[edi]
    mov edx, OFFSET student_info_text
    call write_string
    mov edx, esi
    add edx, OFFSET STUDENT.name
    call write_string
    mov edx, OFFSET age_info_text
    call write_string
    mov ax, students[edi].age
    call write_word
    mov edx, OFFSET phone_info_text
    call write_string
    mov edx, esi
    add edx, OFFSET STUDENT.phone_number
    call write_string
    add edi, TYPE STUDENT
    cmp edi, student_count * TYPE STUDENT
    jb display_students_loop
    jmp display_all_students_end
    all_students_empty:
    mov edx, OFFSET empty_list_text
    call write_string
    display_all_students_end:
ret
display_all_students ENDP
empty_list_text BYTE "The student list is empty.", 13, 10, 0

八、主程序

1. main过程

在主程序中,首先初始化相关的段寄存器和数据,然后进入一个循环,不断调用display_menu函数显示菜单,根据用户的选择调用相应的函数来执行添加、删除、查找或显示学生信息等操作,直到用户选择退出(输入'5')。

.686p
.MODEL flat, stdcall
.STACK 4096
INCLUDE io.asm ; 假设包含了输入输出相关的函数定义文件
.DATA
    students STUDENT 100 DUP(?)
    student_count DWORD 0
.CODE
main PROC
    ; 初始化数据段寄存器
    mov ax, @data
    mov ds, ax
    main_loop:
    call display_menu
    cmp al, '1'
    je add_student_choice
    cmp al, '2'
    je delete_student_choice
    cmp al, '3'
    je find_student_choice
    cmp al, '4'
    je display_all_students_choice
    cmp al, '5'
    je exit_choice
    jmp main_loop
    add_student_choice:
    call add_student
    jmp main_loop
    delete_student_choice:
    call delete_student
    jmp main_loop
    find_student_choice:
    call find_student
    jmp main_loop
    display_all_students_choice:
    call display_all_students
    jmp main_loop
    exit_choice:
    mov eax, 0
    ret
main ENDP
END main

在上述代码中,还需要包含一些输入输出相关的函数,如write_string用于显示字符串,read_char用于读取单个字符,read_word用于读取16位整数等。这些函数的具体实现可以根据实际的输入输出需求和环境进行编写。例如,在Windows环境下,可以使用系统调用或相关的库函数来实现这些输入输出操作。

请注意,这只是一个简单的示例,实际的通讯录可能需要更完善的错误处理、数据验证和用户界面交互等功能。你可以根据自己的需求进一步扩展和优化这个代码。

64位汇编语言基础