Thread: Lost on struct and stack byte ordering

  1. #1
    Registered User
    Join Date
    Jul 2014
    Posts
    3

    Lost on struct and stack byte ordering

    I am working my way through Computer Systems: A Programmer's Perspective for a class and my professor is less than readily available for questions. We have an exam on Friday and I am going through the study materials and past exams he supplied us, but I am hung up on a few questions. I am hoping somebody can explain how to solve them or point me to a good resource to figure them out, Here are the questions I am stuck on:

    1. Assume you’ve been given the following program fragment with a struct that contains only scalars except for one entry.

    Code:
    struct foo {
    
    ______________
    ______________
    ______________
    ______________E[3];
    ______________
    ______________
    };
    
    int
    bar(struct foo *f)
    {
    
    f[1].C = f[0].B > f[2].C;
    f[0].E[-1] = f[0].D;
    f[0].A = f[1].C;
    
    
    }
    producing the assembly code:

    Code:
    bar:
    
    pushl %ebp
    movl %esp, %ebp
    movl 8(%ebp), %eax
    movzbl 65(%eax), %ecx
    cmpb %cl, 24(%eax)
    setg %dl
    movb %dl, 33(%eax)
    movl 28(%eax), %ecx
    movl %ecx, 8(%eax)
    movb %dl, (%eax)
    popl %ebp
    ret
    Knowing the struct contains precisely five scalar variables (A, B, C, D, F) and one array (E), use the C alignment rules for Linux and variable sizes to determine both the order in which the variables are declared and the types of those variables.

    I tried to find the alignment rules and information in the book and online, but can't find any clear explanations.

    2. This program reads a string on standard input and prints an integer in hexadecimal format based on the input string it read.

    Code:
    #include <stdio.h>
    
    /
    *
    Read a string from stdin into buf
    
    *
    /
    int evil_read_string()
    {
    int buf[3];
    scanf("%s",buf);
    return buf[1];
    }
    int main()
    {
    printf("0x%x\n", evil_read_string());
    }
    assembly code:

    Code:
    080483a4 <evil_read_string>:
    
    80483a4: 55                    push   %ebp
    80483a5: 89 e5                 mov    %esp,%ebp
    
    80483a7: 83 ec 18              sub    $0x18,%esp
    80483aa: 8d 45 f4              lea    -0xc(%ebp),%eax
    80483ad: 89 44 24 04           mov    %eax,0x4(%esp)
    //address arg for scanf
    80483b1: c7 04 24 c0 84 04 08  movl   $0x80484c0,(%esp)
    format string for scanf
    80483b8: e8 3f ff ff ff        call   80482fc <scanf@plt>
    //call scanf
    80483bd: 8b 45 f8              mov    -0x8(%ebp),%eax
    80483c0: c9                    leave
    80483c1: c3                    ret
    080483c2 <main>:
    80483c2: 8d 4c 24 04           lea    0x4(%esp),%ecx
    80483c6: 83 e4 f0              and    $0xfffffff0,%esp
    80483c9: ff 71 fc              pushl  -0x4(%ecx)
    80483cc: 55                    push   %ebp
    80483cd: 89 e5                 mov    %esp,%ebp
    80483cf: 51                    push   %ecx
    80483d0: 83 ec 14              sub    $0x14,%esp
    80483d3: e8 cc ff ff ff        call   80483a4 <evil_read_string>
    80483d8: 89 44 24 04           mov    %eax,0x4(%esp)
    //integer arg for printf
    80483dc: c7 04 24 c3 84 04 08  movl   $0x80484c3,(%esp)
    format string for printf
    80483e3: e8 24 ff ff ff        call   804830c <printf@plt>
    //call printf
    80483e8: 83 c4 14              add    $0x14,%esp
    80483eb: 59                    pop    %ecx
    80483ec: 5d                    pop    %ebp
    80483ed: 8d 61 fc              lea    -0x4(%ecx),%esp
    scanf("%s", buf)

    reads an input string from the standard input stream (stdin) and stores it at address buf (including the terminating ’\0’ character). It does not check the size of the destination buffer.
    •printf("0x%x", i) prints the integer i in hexadecimal format preceded by “0x”.
    •Recall that Linux/x86 machines are Little Endian.
    •You will need to know the hex values of the following characters

    Character Hex Value Character Hex Value
    'd' 0x64 'v' 0x76
    'r' 0x72 'i' 0x69
    '.' 0x2e 'l' 0x6c
    'e' 0x65 '\0' 0x00
    'w' 0x77 'n' 0x6E
    's' 0x73 't' 0x74


    Suppose we run this program on a Linux/x86 machine, and give it the string “

    dr.evilwins” as input on stdin.


    ill in the value of buf[1] (in hexadecimal) and indicate where ebp points just after scanf returns to evil_read_string

    _________________________________

    What is the 4-byte integer (in hex) printed by the printf inside main?

    0x______________________

    Suppose now we give it the input "dr.eviltwin.lives" (again on a Linux/x86 machine).

    List the contents of the following memory locations just after scanf returns to evil_read_string. Each answer should be an unsigned 4-byte integer expressed as 8 hex digits.

    buf[0] = 0x__________________

    buf[4] = 0x__________________

    Immediately before the ret instruction at address 0x08048435 executes, what is the value of the frame pointer register %ebp?

    %ebp = 0x__________________

    __________________________________________________ ____________

    Any help would be greatly appreciated!

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    The way it works here is that you make your best attempt, and ask us specific questions, and we give answers. You can't just post your homework and say "help please".

    As for alignment, the basic rule is that data types that are N bytes in size must have an address that is a multiple of N. Thus a 2 byte type like short can theoretically exist at address 0x2, 0x4, 0x12756, etc. A 4 byte type can only exist at addresses that are a multiple of 4.

    This should also be at least somewhat helpful: Intel x86 Function-call Conventions - Assembly View.

    Give it your best shot. Tell us what you think the answers are, and why​, and we'll help you fix your misunderstandings.

  3. #3
    Registered User
    Join Date
    Jul 2014
    Posts
    3
    Quote Originally Posted by anduril462 View Post
    The way it works here is that you make your best attempt, and ask us specific questions, and we give answers. You can't just post your homework and say "help please".

    As for alignment, the basic rule is that data types that are N bytes in size must have an address that is a multiple of N. Thus a 2 byte type like short can theoretically exist at address 0x2, 0x4, 0x12756, etc. A 4 byte type can only exist at addresses that are a multiple of 4.

    This should also be at least somewhat helpful: Intel x86 Function-call Conventions - Assembly View.

    Give it your best shot. Tell us what you think the answers are, and why​, and we'll help you fix your misunderstandings.
    I was looking for references and resources, not for someone to do the work for me. Thanks, the link helps. I will post what I have done thus far in a few minutes.

  4. #4
    Registered User
    Join Date
    Jul 2014
    Posts
    3
    OK, so I guess what is really confusing me on the first one is what is going on with the function pointer in the arguments for bar. None of the examples in the book even remotely address this. What are f[0], f[1], and f[2] in this context? Are these single structures with member variables? So would f[1] and f[0], for example, be individual structures? I can't wrap my mind around the intuition here.

    Code:
    int
    
    bar(struct foo *f)
    {
    
     
    f[1].C = f[0].B > f[2].C;
    
    f[0].E[-1] = f[0].D;
    f[0].A = f[1].C;
     
     
    
    }

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    It's not a function pointer, it's a pointer to struct. Recall that arrays, when passed to functions, decay to a pointer to the first element. f represents an array of struct, just like you can write a function that handles char arrays representing string data. Something like:
    Code:
    void foo(char *s) {
        s[2] = 'x';  // make the 3rd char an 'x'
    }
    ...
    char bar[10] = "foobar";
    foo(bar);
    // bar should now be "foxbar"

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Byte Ordering Question
    By Syndacate in forum C Programming
    Replies: 14
    Last Post: 04-15-2014, 12:10 PM
  2. convert struct to host byte order
    By jean.yves in forum C Programming
    Replies: 13
    Last Post: 12-15-2010, 03:06 PM
  3. struct data changes lost?
    By six in forum C++ Programming
    Replies: 2
    Last Post: 04-24-2010, 07:57 PM
  4. Endian change & Byte Array -> Struct
    By bramaen in forum C Programming
    Replies: 3
    Last Post: 02-05-2010, 12:55 PM
  5. Struct (with pointer) to byte array
    By rabencor in forum C Programming
    Replies: 1
    Last Post: 02-08-2009, 05:27 AM

Tags for this Thread