MIPS平台文件局部修改技术咨询:如何避免全文件覆盖?
Great question! In MIPS, you absolutely can use file pointers (or file descriptors, depending on whether you're working in C or raw assembly) to modify files locally instead of overwriting the entire thing. Let's break this down step by step, using your exact example of replacing 20th with 21st.
Core Concept First
Local modification boils down to precise positioning: find the exact byte offset of the text you want to change, then write your replacement content directly to that spot. Since your replacement text (21st) and original text (20th) are the same length (4 characters each), this is the simplest scenario—you can overwrite those bytes without disrupting the rest of the file. If the lengths differed, we'd need extra steps to shift content, but let's focus on your use case first.
Option 1: Using MIPS C (Easier for Beginners)
If you're writing MIPS code in C (compiled for the MIPS architecture), standard C file I/O functions handle file pointers seamlessly:
- Open the file in read-write mode: Use
fopen()with"r+"—this lets you read and write without truncating the original file (unlike"w"which wipes content). - Locate the target string: Read chunks of the file into a buffer, then use
strstr()to find where 20th starts. - Seek to the target position: Calculate the exact offset from the file's start, then use
fseek()to move the file pointer there. - Write the replacement: Use
fwrite()to overwrite the 4 characters with 21st. - Clean up: Always close the file with
fclose().
Here's a working code snippet for your example:
#include <stdio.h> #include <string.h> int main() { FILE *fp = fopen("birthday.txt", "r+"); if (!fp) { perror("Failed to open file"); return 1; } char buffer[256]; while (fgets(buffer, sizeof(buffer), fp)) { // Search for the target substring char *target_pos = strstr(buffer, "20th"); if (target_pos) { // Calculate offset from file start: current position minus buffer length, plus target's position in buffer long file_offset = ftell(fp) - strlen(buffer) + (target_pos - buffer); // Move pointer to the start of "20th" fseek(fp, file_offset, SEEK_SET); // Write the 4-character replacement fwrite("21st", sizeof(char), 4, fp); break; // Exit after making the change } } fclose(fp); return 0; }
Option 2: Raw MIPS Assembly (Using System Calls)
For pure MIPS assembly, you'll work directly with file descriptors and system calls instead of C-style file pointers. The logic stays the same: open → locate → seek → write → close.
Key MIPS system calls you'll need:
1024:open()(retrieve a file descriptor)1029:lseek()(move the file pointer to a specific offset)1026:write()(write replacement bytes)1027:close()(close the file)
First, you'll need to read the file byte-by-byte to find the offset of 20th (this involves looping and comparing each character to the target sequence). Once you have that offset, here's how to perform the write:
.data filename: .asciiz "birthday.txt" replace_str: .asciiz "21st" # 4-byte replacement string .text .globl main main: # Step 1: Open file in read-write mode (O_RDWR = 0x02) li $v0, 1024 la $a0, filename li $a1, 0x02 # O_RDWR flag li $a2, 0644 # File permissions (read/write for owner) syscall move $s0, $v0 # Save file descriptor to $s0 # Step 2: Seek to the target offset (replace `target_offset` with your calculated value) li $v0, 1029 move $a0, $s0 li $a1, target_offset # Offset from file start to "20th" li $a2, 0 # SEEK_SET (start counting from file beginning) syscall # Step 3: Write the replacement string li $v0, 1026 move $a0, $s0 la $a1, replace_str li $a2, 4 # Write 4 bytes total syscall # Step 4: Close the file li $v0, 1027 move $a0, $s0 syscall # Exit program li $v0, 10 syscall
Important Edge Case Notes
- Different replacement lengths: If you needed to replace a string with a longer/shorter one (e.g., 20th → 21st Birthday!), direct overwriting won't work. Instead, you'll need to:
- Read the entire file into memory.
- Modify the content in memory.
- Truncate the original file (or create a new one) and write the modified content back.
- Error handling: Always check return values (e.g., if
open()returns -1, the file couldn't be opened). - Assembly string matching: To find 20th in assembly, loop through each byte, compare sequentially to '2', '0', 't', 'h', and track the offset when a full match is found.
内容的提问来源于stack exchange,提问作者MonkeyD

