Operating Systems 2026F: Assignment 1: Difference between revisions

From Soma-notes
No edit summary
No edit summary
Line 1: Line 1:
'''This assignment is not yet finalized.'''
Please submit the answers to the following questions via Brightspace by October 5, 2026. There are 20 points in eight questions.
Please submit the answers to the following questions via Brightspace by October 5, 2026. There are 20 points in eight questions.



Revision as of 20:31, 27 September 2026

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-assign1-<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.

  1. [2] How do you define a custom command for 3000menu without changing its code? What parts 3000menu implement custom command support?
  2. [2] Can menu commands include command line options? Why, or why not?
  3. [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.
  4. [2] Which line(s) in 3000menu.s implement the if/else statements in run_program()? How do you know those are the correct lines?
  5. [2] What line(s) in 3000menu.s implement the call to getline() in choose_program()? How do you know those are the correct lines?
  6. [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)?
  7. [2] Does the code in 3000menu.s make any system calls directly? How do you know? Explain briefly.
  8. [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

/* 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);
                }
        }
}

3000menu.s

	.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: