在x86 MASM汇编中从文件随机选取8个单词的实现方法
Great to see you've already nailed the file reading and console display basics! Let's build on that code to pick 8 unique random words from your 500-word list. Here's a step-by-step breakdown of how to make this work:
Step 1: Parse the File into a Word Array
Your text uses the format 1. abacus (number + period + space + word), so first we need to strip out the extra characters and store just the words in an array.
After reading the file into your buffer, iterate through the content to:
- Skip past the number, period, and space to reach the start of each word
- Copy each word into a dedicated slot in an array (make sure each slot is big enough for your longest word plus a null terminator)
- Track how many words you've parsed (we know it's 500, but dynamic counting makes the code more flexible)
Example Parsing Snippet
; Assumptions: ; - buffer contains the full file content ; - wordArray is a pre-allocated array of byte strings (each slot ~20 bytes for most English words) ; - wordCount tracks total parsed words mov esi, offset buffer ; Start at the beginning of the file content mov edi, offset wordArray ; Point to the start of our word storage array mov ecx, 0 ; Initialize word counter to 0 parse_loop: ; Skip characters until we hit the ". " separator cmp byte ptr [esi], '.' jne skip_char cmp byte ptr [esi+1], ' ' jne skip_char add esi, 2 ; Move past ". " to the start of the word mov ebx, edi ; Save the start of this word's slot ; Copy the word until we hit a newline or end of buffer copy_word: mov al, [esi] cmp al, 0Ah ; Check for newline (ASCII line feed) je end_of_word cmp al, 0 ; Check for end of buffer je end_parsing mov [edi], al inc edi inc esi jmp copy_word end_of_word: mov byte ptr [edi], 0 ; Null-terminate the word inc edi ; Move to the next word slot (adjust based on your slot size) inc ecx ; Increment word count inc esi ; Move past the newline cmp ecx, 500 ; Stop once we've parsed all 500 words jl parse_loop end_parsing: mov wordCount, ecx ; Store the total number of words
Step 2: Add Random Number Generation
MASM doesn't have a built-in random function, but we can use Windows API's RtlRandom (from ntdll.dll) seeded with the system time to get unique random results each run.
Random Seed & Generator Setup
; sysTime is a SYSTEMTIME structure to hold current time invoke GetSystemTime, offset sysTime ; Combine time values into a 32-bit seed mov eax, [sysTime.wYear] shl eax, 16 mov ax, [sysTime.wMonth] shl eax, 8 mov al, [sysTime.wDay] xor eax, [sysTime.wHour] xor eax, [sysTime.wMinute] xor eax, [sysTime.wSecond] mov seed, eax ; Initialize the random generator (RtlRandom modifies the seed pointer) invoke RtlRandom, offset seed
Step 3: Select 8 Unique Words
Generate random indices (0 to 499) and pick the corresponding words. We'll track used indices to avoid duplicates.
Selection & Display Snippet
; usedIndices is a 500-byte array initialized to 0 (0 = unused, 1 = used) ; selectedWords stores pointers to the 8 chosen words mov ecx, 0 ; Counter for selected words select_loop: cmp ecx, 8 je done_selecting ; Generate a random index between 0 and 499 invoke RtlRandom, offset seed xor edx, edx mov ebx, 500 div ebx ; edx holds the random index mov esi, edx ; Skip if this index was already used cmp byte ptr [usedIndices + esi], 1 je select_loop ; Mark index as used and store the word pointer mov byte ptr [usedIndices + esi], 1 mov eax, offset wordArray mov ebx, 20 ; Size of each word slot (adjust to match your array) mul esi add eax, offset wordArray mov [selectedWords + ecx*4], eax inc ecx jmp select_loop done_selecting: ; Display the 8 selected words mov ecx, 0 display_loop: cmp ecx, 8 je done_displaying invoke GetStdHandle, -11 mov edx, [selectedWords + ecx*4] ; Calculate word length for WriteConsoleA mov ebx, edx mov eax, 0 count_length: cmp byte ptr [ebx], 0 je end_count inc eax inc ebx jmp count_length end_count: invoke WriteConsoleA, eax, edx, eax, offset x, 0 ; Print a newline after each word mov edx, offset newline invoke WriteConsoleA, eax, edx, 1, offset x, 0 inc ecx jmp display_loop done_displaying:
Quick Tips
- Buffer Size: Ensure your initial buffer is large enough to hold the entire 500-word file. If not, modify your
ReadFilecall to read in chunks. - Null Termination: Always null-terminate strings when using Windows API functions like
WriteConsoleA—it prevents garbage output. - Slot Size: Adjust the word array slot size (20 in the example) to fit the longest word in your list.
内容的提问来源于stack exchange,提问作者Anmol Wajid

