Недавно я обнаружил ошибку в user/syscall.c
, которая может повлиять на вас.Попробуйте применить этот патч к user/syscall.c
:
diff --git a/src/lib/user/syscall.c b/src/lib/user/syscall.c
index a9c5bc8..efeb38c 100644
--- a/src/lib/user/syscall.c
+++ b/src/lib/user/syscall.c
@@ -10,7 +10,7 @@
("pushl %[number]; int $0x30; addl $4, %%esp" \
: "=a" (retval) \
: [number] "i" (NUMBER) \
- : "memory"); \
+ : "memory", "esp"); \
retval; \
})
@@ -24,7 +24,7 @@
: "=a" (retval) \
: [number] "i" (NUMBER), \
[arg0] "g" (ARG0) \
- : "memory"); \
+ : "memory", "esp"); \
retval; \
})
@@ -40,7 +40,7 @@
: [number] "i" (NUMBER), \
[arg0] "g" (ARG0), \
[arg1] "g" (ARG1) \
- : "memory"); \
+ : "memory", "esp"); \
retval; \
})
@@ -57,7 +57,7 @@
[arg0] "g" (ARG0), \
[arg1] "g" (ARG1), \
[arg2] "g" (ARG2) \
- : "memory"); \
+ : "memory", "esp" ); \
retval; \
})
Вот длинная история ...
Например, в макросе syscall3
ожидаемый генерируемый код сборки выглядит примерно так:this
pushl ARG2
pushl ARG1
pushl ARG0
pushl NUMBER
int $0x30
addl $16, %esp
Это должно работать до тех пор, пока стек выглядит точно так, как ожидается, просто нажмите инструкцию прерывания.Вот как выглядит дизассемблированная функция write
в тестовых программах (сгенерированных objdump -d pintos/src/userprog/build/tests/userprog/args-many
):
0804a1a5 <write>:
804a1a5: ff 74 24 0c pushl 0xc(%esp)
804a1a9: ff 74 24 08 pushl 0x8(%esp)
804a1ad: ff 74 24 04 pushl 0x4(%esp)
804a1b1: 6a 09 push $0x9
804a1b3: cd 30 int $0x30
804a1b5: 83 c4 10 add $0x10,%esp
804a1b8: c3 ret
С этими инструкциями связана огромная проблема.Поскольку аргументы помещаются в стек относительно указателя стека %esp
, неправильные аргументы помещаются в стек!Это связано с тем, что %esp
меняется после каждой pushl
инструкции.
После некоторого изучения расширенного синтаксиса asm для gcc, я думаю, что нашел правильное решение.Регистр %esp
необходимо добавить в список Clobbers в расширенной инструкции asm для каждого syscall*
.Это связано с тем, что каждая инструкция pushl
изменяет %esp
косвенно, поэтому мы должны сообщить gcc об этой модификации, чтобы она не использовала %esp
неправильно в сгенерированных инструкциях.