Operating Systems 2026F: Assignment 1
Please submit the answers to the following questions via Brightspace by October 5, 2026. There are 20 points in eight questions.
Submit your answers as a plain text file following this template. Name your answer file "comp3000-a1-<username>.txt" (where username is your MyCarletonOne username). Please make sure to use your correct student ID number otherwise your grades may not be properly recorded.
Your answers will be parsed by a script in order to help with grading so please preserve the format of the template. No other formats will be accepted.
Note that the file should be a UNIX text file, not a Windows text file (so LF line endings). See the Wikipedia page on text files to learn more. Most modern text editors can convert between different types of text files. Alternately, install the program dos2unix on the VM to convert.
You may use this validator page to make sure your answer file is properly named and formatted.
Don't forget to include what outside resources you used to complete each of your answers, including other students, man pages, and web resources. You do not need to list help from the instructor, TA, or information found in the textbook.
Introduction
In this assignment you will be looking at 3000menu.c and its corresponding assembly language version, 3000menu.s. You can download the C source, generate the assembly language code, and compile it with the following commands:
wget https://homeostasis.scs.carleton.ca/~soma/os-2026f/code/3000menu.c gcc -O -S 3000menu.c gcc -O 3000menu.c -o 3000menu
Note that you can also just compile the assembly code directly:
gcc -O 3000menu.s -o 3000menu
If ltrace doesn't work for you, add the "-z lazy" option when you compile. (This option is not needed on Ubuntu 26.04.)
Questions
Please answer the following questions. When a question asks about how do you know, you need to give empirical evidence. References to documentation are not sufficient as documentation can be incorrect.
- [2] How do you define a custom command for 3000menu without changing its code? What parts 3000menu implement custom command support?
- [2] Can menu commands include command line options? Why, or why not?
- [2] What compiler directive (an instruction starting with a period) is present at the start of every function? What is at the end of the function? Ignore directives that include the name of the function.
- [2] Which line(s) in 3000menu.s implement the if/else statements in run_program()? How do you know those are the correct lines?
- [2] What line(s) in 3000menu.s implement the call to getline() in choose_program()? How do you know those are the correct lines?
- [2] printf calls get translated into two different calls in assembly. What are those two calls? And why is each used (rather than the other)?
- [2] Does the code in 3000menu.s make any system calls directly? How do you know? Explain briefly.
- [6] How could you modify 3000menu.c so that run_program() no longer used system() and instead used fork, execve, and any code from the first two tutorials except for execvp()? You may not use any other external code. Your modified version should have equivalent functionality to the original.
Code
/* 3000menu.c */
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
char *menu[] = {
"/usr/bin/ls",
"/usr/bin/ps",
"/usr/bin/nano",
"/usr/bin/top",
"CUSTOM",
"QUIT",
NULL
};
int quit = 5;
const int CUSTOM = 4;
void run_program(int choice)
{
int result;
printf("Running %s\n", menu[choice]);
result = system(menu[choice]);
if (result != 0) {
printf("Command failed.\n");
} else {
printf("Command succeeded.\n");
}
return;
}
int choose_program(void)
{
int i = 0;
int choice;
char *input = NULL;
size_t result, n = 0;
printf("\nChoose a program to run:\n\n");
while (i <= quit) {
printf("%d. %s\n", i + 1, menu[i]);
i++;
}
printf("\nYour choice? ");
result = getline(&input, &n, stdin);
choice = atoi(input);
free(input);
if ((result > 0) && (choice > 0) && (choice <= i)) {
return choice - 1;
} else {
return -1;
}
}
int main()
{
int program;
char *c;
c = getenv("MENUCMD");
if (c) {
menu[CUSTOM] = c;
} else {
menu[CUSTOM] = menu[quit];
quit = CUSTOM;
}
while (1) {
program = choose_program();
if (program == quit) {
return 0;
}
if (program != -1) {
run_program(program);
}
}
}
.file "3000menu.c"
.text
.section .rodata.str1.1,"aMS",@progbits,1
.LC0:
.string "Running %s\n"
.LC1:
.string "Command failed."
.LC2:
.string "Command succeeded."
.text
.globl run_program
.type run_program, @function
run_program:
.LFB51:
.cfi_startproc
endbr64
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
pushq %rbx
.cfi_def_cfa_offset 24
.cfi_offset 3, -24
subq $8, %rsp
.cfi_def_cfa_offset 32
leaq menu(%rip), %rbp
movslq %edi, %rbx
movq 0(%rbp,%rbx,8), %rdx
leaq .LC0(%rip), %rsi
movl $2, %edi
movl $0, %eax
call __printf_chk@PLT
movq 0(%rbp,%rbx,8), %rdi
call system@PLT
testl %eax, %eax
je .L2
leaq .LC1(%rip), %rdi
call puts@PLT
.L1:
addq $8, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 24
popq %rbx
.cfi_def_cfa_offset 16
popq %rbp
.cfi_def_cfa_offset 8
ret
.L2:
.cfi_restore_state
leaq .LC2(%rip), %rdi
call puts@PLT
jmp .L1
.cfi_endproc
.LFE51:
.size run_program, .-run_program
.section .rodata.str1.1
.LC3:
.string "\nChoose a program to run:\n"
.LC4:
.string "%d. %s\n"
.LC5:
.string "\nYour choice? "
.text
.globl choose_program
.type choose_program, @function
choose_program:
.LFB52:
.cfi_startproc
endbr64
pushq %r12
.cfi_def_cfa_offset 16
.cfi_offset 12, -16
pushq %rbp
.cfi_def_cfa_offset 24
.cfi_offset 6, -24
pushq %rbx
.cfi_def_cfa_offset 32
.cfi_offset 3, -32
subq $32, %rsp
.cfi_def_cfa_offset 64
movq %fs:40, %rax
movq %rax, 24(%rsp)
xorl %eax, %eax
movq $0, 8(%rsp)
movq $0, 16(%rsp)
leaq .LC3(%rip), %rdi
call puts@PLT
cmpl $0, quit(%rip)
js .L9
leaq menu(%rip), %rbp
movl $0, %ebx
leaq .LC4(%rip), %r12
.L7:
addl $1, %ebx
movq 0(%rbp), %rcx
movl %ebx, %edx
movq %r12, %rsi
movl $2, %edi
movl $0, %eax
call __printf_chk@PLT
addq $8, %rbp
cmpl quit(%rip), %ebx
jle .L7
.L6:
leaq .LC5(%rip), %rsi
movl $2, %edi
movl $0, %eax
call __printf_chk@PLT
leaq 16(%rsp), %rsi
leaq 8(%rsp), %rdi
movq stdin(%rip), %rdx
call getline@PLT
movq %rax, %r12
movl $10, %edx
movl $0, %esi
movq 8(%rsp), %rdi
call __isoc23_strtol@PLT
movq %rax, %rbp
movq 8(%rsp), %rdi
call free@PLT
testl %ebp, %ebp
setg %dl
cmpl %ebx, %ebp
setle %al
andl %eax, %edx
testq %r12, %r12
setne %al
movzbl %al, %eax
andl %edx, %eax
negl %eax
andl %ebp, %eax
subl $1, %eax
movq 24(%rsp), %rdx
subq %fs:40, %rdx
jne .L12
addq $32, %rsp
.cfi_remember_state
.cfi_def_cfa_offset 32
popq %rbx
.cfi_def_cfa_offset 24
popq %rbp
.cfi_def_cfa_offset 16
popq %r12
.cfi_def_cfa_offset 8
ret
.L9:
.cfi_restore_state
movl $0, %ebx
jmp .L6
.L12:
call __stack_chk_fail@PLT
.cfi_endproc
.LFE52:
.size choose_program, .-choose_program
.section .rodata.str1.1
.LC6:
.string "MENUCMD"
.text
.globl main
.type main, @function
main:
.LFB53:
.cfi_startproc
endbr64
subq $8, %rsp
.cfi_def_cfa_offset 16
leaq .LC6(%rip), %rdi
call getenv@PLT
testq %rax, %rax
je .L14
movq %rax, 32+menu(%rip)
.L18:
call choose_program
cmpl %eax, quit(%rip)
je .L20
cmpl $-1, %eax
je .L18
movl %eax, %edi
call run_program
jmp .L18
.L14:
movslq quit(%rip), %rdx
leaq menu(%rip), %rax
movq (%rax,%rdx,8), %rax
movq %rax, 32+menu(%rip)
movl $4, quit(%rip)
jmp .L18
.L20:
movl $0, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE53:
.size main, .-main
.globl CUSTOM
.section .rodata
.align 4
.type CUSTOM, @object
.size CUSTOM, 4
CUSTOM:
.long 4
.globl quit
.data
.align 4
.type quit, @object
.size quit, 4
quit:
.long 5
.globl menu
.section .rodata.str1.1
.LC7:
.string "/usr/bin/ls"
.LC8:
.string "/usr/bin/ps"
.LC9:
.string "/usr/bin/nano"
.LC10:
.string "/usr/bin/top"
.LC11:
.string "CUSTOM"
.LC12:
.string "QUIT"
.section .data.rel.local,"aw"
.align 32
.type menu, @object
.size menu, 56
menu:
.quad .LC7
.quad .LC8
.quad .LC9
.quad .LC10
.quad .LC11
.quad .LC12
.quad 0
.ident "GCC: (Ubuntu 15.2.0-16ubuntu1) 15.2.0"
.section .note.GNU-stack,"",@progbits
.section .note.gnu.property,"a"
.align 8
.long 1f - 0f
.long 4f - 1f
.long 5
0:
.string "GNU"
1:
.align 8
.long 0xc0000002
.long 3f - 2f
2:
.long 0x3
3:
.align 8
4: