Draw the stack frame and determin addresses of locals assuming x86 calling convention










1















int fun (short a,long b, int c)short q; char s[3]; int y; 


My stack frame looks like this: (I'm not sure)



enter image description here



Two questions:



  1. Is it good?

  2. In this convention stack is with increasing addresses and heap with decreasing?









share|improve this question
























  • You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

    – Jester
    Nov 14 '18 at 0:04












  • I'll add it. So everything else seems to be fine?

    – sswwqqaa
    Nov 14 '18 at 0:07











  • Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

    – sswwqqaa
    Nov 14 '18 at 0:09







  • 1





    Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

    – Jester
    Nov 14 '18 at 0:10






  • 1





    Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

    – Peter Cordes
    Nov 14 '18 at 0:27















1















int fun (short a,long b, int c)short q; char s[3]; int y; 


My stack frame looks like this: (I'm not sure)



enter image description here



Two questions:



  1. Is it good?

  2. In this convention stack is with increasing addresses and heap with decreasing?









share|improve this question
























  • You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

    – Jester
    Nov 14 '18 at 0:04












  • I'll add it. So everything else seems to be fine?

    – sswwqqaa
    Nov 14 '18 at 0:07











  • Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

    – sswwqqaa
    Nov 14 '18 at 0:09







  • 1





    Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

    – Jester
    Nov 14 '18 at 0:10






  • 1





    Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

    – Peter Cordes
    Nov 14 '18 at 0:27













1












1








1








int fun (short a,long b, int c)short q; char s[3]; int y; 


My stack frame looks like this: (I'm not sure)



enter image description here



Two questions:



  1. Is it good?

  2. In this convention stack is with increasing addresses and heap with decreasing?









share|improve this question
















int fun (short a,long b, int c)short q; char s[3]; int y; 


My stack frame looks like this: (I'm not sure)



enter image description here



Two questions:



  1. Is it good?

  2. In this convention stack is with increasing addresses and heap with decreasing?






assembly x86






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 0:19









Peter Cordes

128k18190326




128k18190326










asked Nov 14 '18 at 0:00









sswwqqaasswwqqaa

6101314




6101314












  • You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

    – Jester
    Nov 14 '18 at 0:04












  • I'll add it. So everything else seems to be fine?

    – sswwqqaa
    Nov 14 '18 at 0:07











  • Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

    – sswwqqaa
    Nov 14 '18 at 0:09







  • 1





    Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

    – Jester
    Nov 14 '18 at 0:10






  • 1





    Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

    – Peter Cordes
    Nov 14 '18 at 0:27

















  • You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

    – Jester
    Nov 14 '18 at 0:04












  • I'll add it. So everything else seems to be fine?

    – sswwqqaa
    Nov 14 '18 at 0:07











  • Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

    – sswwqqaa
    Nov 14 '18 at 0:09







  • 1





    Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

    – Jester
    Nov 14 '18 at 0:10






  • 1





    Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

    – Peter Cordes
    Nov 14 '18 at 0:27
















You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

– Jester
Nov 14 '18 at 0:04






You seem to have allocated 6 bytes for s and 4 for a. Also what's the striped slot after a? b uses 4 bytes as is normally the case on x86, but then why is it drawn with a split box as if it took 8?

– Jester
Nov 14 '18 at 0:04














I'll add it. So everything else seems to be fine?

– sswwqqaa
Nov 14 '18 at 0:07





I'll add it. So everything else seems to be fine?

– sswwqqaa
Nov 14 '18 at 0:07













Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

– sswwqqaa
Nov 14 '18 at 0:09






Also didn't mention that long in my case uses 8 bits (I was told the size of long = 8)

– sswwqqaa
Nov 14 '18 at 0:09





1




1





Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

– Jester
Nov 14 '18 at 0:10





Well, the diagram shows b from 16 to 20, that's 4 bytes not 8.

– Jester
Nov 14 '18 at 0:10




1




1





Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

– Peter Cordes
Nov 14 '18 at 0:27





Anyway, adding some ='a' and so on to your code can get a compiler to generate asm that shows you the locations where it put the variables: godbolt.org/z/ye4OUy. I had to use long long to get a 64-bit integer type when FP and the return address were still only 4 bytes; no standard x86 calling convention / ABI has 64-bit long in 32-bit mode. But anyway, both MSVC on Windows and gcc on Linux agree that a,b,c are at 8,12,20

– Peter Cordes
Nov 14 '18 at 0:27












1 Answer
1






active

oldest

votes


















1














There is not a single x86 calling convention and the layout of the local variables is not defined by the calling convention anyway.

The question is thus not framed correctly, even before taking into consideration how the C types are implemented.



If we assume:




  • stdcall or cdecl calling convention.

  • The compiler is using a frame pointer.

  • The compiler will align data at least on their natural boundaries.


  • short, int, long are 16, 32, 32 bits respectively and aligned on 2, 4 and 4 bytes respectively.

then I'd expect this stack (note that I use the hex notation):



[EBP +10h] c
[EBP +0Ch] b
[EBP +08h] a
[EBP +04h] Return address
[EBP +00h] Old EBP
[EBP -02h] q
[EBP -05h] s
[EBP -0ch] y


That's what Clang does without optimisations except that it preserves 3 registers thereby shifting the offsets down by 12.



a, b and c are pushed on the stack in reverse order, all types must occupy a number of bytes multiple of 4.



Locals allocation is not absolute, it depends on the surrounding code (usage of non volatile registers, calls, temporaries, stack protections and so on) and in this case, where there is no code or context at all, the question is a bit vacuous.

Using only the last two assumptions1 we can put q at [EBP -02h] since q is 2 bytes and need to be at an address multiple of 2; s is at [EBP -05h] since it is 3 bytes and is byte-aligned; finally y could go at [EBP -09h] from a size-only perspective but since it must be aligned on 4-bytes, it goes at [EBP -0ch].

Note that all the reasoning above exploit the fact that EBP is aligned on 4-bytes.




1 We also assume that locals are laid out in reverse order: the last one in order of declaration is laid out at a lower address.






share|improve this answer

























  • According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

    – Peter Cordes
    Nov 14 '18 at 16:02











  • @PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

    – Margaret Bloom
    Nov 14 '18 at 16:25











  • That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

    – Peter Cordes
    Nov 14 '18 at 16:28












  • @PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

    – Margaret Bloom
    Nov 15 '18 at 13:45










Your Answer






StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













draft saved

draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291230%2fdraw-the-stack-frame-and-determin-addresses-of-locals-assuming-x86-calling-conve%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














There is not a single x86 calling convention and the layout of the local variables is not defined by the calling convention anyway.

The question is thus not framed correctly, even before taking into consideration how the C types are implemented.



If we assume:




  • stdcall or cdecl calling convention.

  • The compiler is using a frame pointer.

  • The compiler will align data at least on their natural boundaries.


  • short, int, long are 16, 32, 32 bits respectively and aligned on 2, 4 and 4 bytes respectively.

then I'd expect this stack (note that I use the hex notation):



[EBP +10h] c
[EBP +0Ch] b
[EBP +08h] a
[EBP +04h] Return address
[EBP +00h] Old EBP
[EBP -02h] q
[EBP -05h] s
[EBP -0ch] y


That's what Clang does without optimisations except that it preserves 3 registers thereby shifting the offsets down by 12.



a, b and c are pushed on the stack in reverse order, all types must occupy a number of bytes multiple of 4.



Locals allocation is not absolute, it depends on the surrounding code (usage of non volatile registers, calls, temporaries, stack protections and so on) and in this case, where there is no code or context at all, the question is a bit vacuous.

Using only the last two assumptions1 we can put q at [EBP -02h] since q is 2 bytes and need to be at an address multiple of 2; s is at [EBP -05h] since it is 3 bytes and is byte-aligned; finally y could go at [EBP -09h] from a size-only perspective but since it must be aligned on 4-bytes, it goes at [EBP -0ch].

Note that all the reasoning above exploit the fact that EBP is aligned on 4-bytes.




1 We also assume that locals are laid out in reverse order: the last one in order of declaration is laid out at a lower address.






share|improve this answer

























  • According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

    – Peter Cordes
    Nov 14 '18 at 16:02











  • @PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

    – Margaret Bloom
    Nov 14 '18 at 16:25











  • That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

    – Peter Cordes
    Nov 14 '18 at 16:28












  • @PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

    – Margaret Bloom
    Nov 15 '18 at 13:45















1














There is not a single x86 calling convention and the layout of the local variables is not defined by the calling convention anyway.

The question is thus not framed correctly, even before taking into consideration how the C types are implemented.



If we assume:




  • stdcall or cdecl calling convention.

  • The compiler is using a frame pointer.

  • The compiler will align data at least on their natural boundaries.


  • short, int, long are 16, 32, 32 bits respectively and aligned on 2, 4 and 4 bytes respectively.

then I'd expect this stack (note that I use the hex notation):



[EBP +10h] c
[EBP +0Ch] b
[EBP +08h] a
[EBP +04h] Return address
[EBP +00h] Old EBP
[EBP -02h] q
[EBP -05h] s
[EBP -0ch] y


That's what Clang does without optimisations except that it preserves 3 registers thereby shifting the offsets down by 12.



a, b and c are pushed on the stack in reverse order, all types must occupy a number of bytes multiple of 4.



Locals allocation is not absolute, it depends on the surrounding code (usage of non volatile registers, calls, temporaries, stack protections and so on) and in this case, where there is no code or context at all, the question is a bit vacuous.

Using only the last two assumptions1 we can put q at [EBP -02h] since q is 2 bytes and need to be at an address multiple of 2; s is at [EBP -05h] since it is 3 bytes and is byte-aligned; finally y could go at [EBP -09h] from a size-only perspective but since it must be aligned on 4-bytes, it goes at [EBP -0ch].

Note that all the reasoning above exploit the fact that EBP is aligned on 4-bytes.




1 We also assume that locals are laid out in reverse order: the last one in order of declaration is laid out at a lower address.






share|improve this answer

























  • According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

    – Peter Cordes
    Nov 14 '18 at 16:02











  • @PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

    – Margaret Bloom
    Nov 14 '18 at 16:25











  • That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

    – Peter Cordes
    Nov 14 '18 at 16:28












  • @PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

    – Margaret Bloom
    Nov 15 '18 at 13:45













1












1








1







There is not a single x86 calling convention and the layout of the local variables is not defined by the calling convention anyway.

The question is thus not framed correctly, even before taking into consideration how the C types are implemented.



If we assume:




  • stdcall or cdecl calling convention.

  • The compiler is using a frame pointer.

  • The compiler will align data at least on their natural boundaries.


  • short, int, long are 16, 32, 32 bits respectively and aligned on 2, 4 and 4 bytes respectively.

then I'd expect this stack (note that I use the hex notation):



[EBP +10h] c
[EBP +0Ch] b
[EBP +08h] a
[EBP +04h] Return address
[EBP +00h] Old EBP
[EBP -02h] q
[EBP -05h] s
[EBP -0ch] y


That's what Clang does without optimisations except that it preserves 3 registers thereby shifting the offsets down by 12.



a, b and c are pushed on the stack in reverse order, all types must occupy a number of bytes multiple of 4.



Locals allocation is not absolute, it depends on the surrounding code (usage of non volatile registers, calls, temporaries, stack protections and so on) and in this case, where there is no code or context at all, the question is a bit vacuous.

Using only the last two assumptions1 we can put q at [EBP -02h] since q is 2 bytes and need to be at an address multiple of 2; s is at [EBP -05h] since it is 3 bytes and is byte-aligned; finally y could go at [EBP -09h] from a size-only perspective but since it must be aligned on 4-bytes, it goes at [EBP -0ch].

Note that all the reasoning above exploit the fact that EBP is aligned on 4-bytes.




1 We also assume that locals are laid out in reverse order: the last one in order of declaration is laid out at a lower address.






share|improve this answer















There is not a single x86 calling convention and the layout of the local variables is not defined by the calling convention anyway.

The question is thus not framed correctly, even before taking into consideration how the C types are implemented.



If we assume:




  • stdcall or cdecl calling convention.

  • The compiler is using a frame pointer.

  • The compiler will align data at least on their natural boundaries.


  • short, int, long are 16, 32, 32 bits respectively and aligned on 2, 4 and 4 bytes respectively.

then I'd expect this stack (note that I use the hex notation):



[EBP +10h] c
[EBP +0Ch] b
[EBP +08h] a
[EBP +04h] Return address
[EBP +00h] Old EBP
[EBP -02h] q
[EBP -05h] s
[EBP -0ch] y


That's what Clang does without optimisations except that it preserves 3 registers thereby shifting the offsets down by 12.



a, b and c are pushed on the stack in reverse order, all types must occupy a number of bytes multiple of 4.



Locals allocation is not absolute, it depends on the surrounding code (usage of non volatile registers, calls, temporaries, stack protections and so on) and in this case, where there is no code or context at all, the question is a bit vacuous.

Using only the last two assumptions1 we can put q at [EBP -02h] since q is 2 bytes and need to be at an address multiple of 2; s is at [EBP -05h] since it is 3 bytes and is byte-aligned; finally y could go at [EBP -09h] from a size-only perspective but since it must be aligned on 4-bytes, it goes at [EBP -0ch].

Note that all the reasoning above exploit the fact that EBP is aligned on 4-bytes.




1 We also assume that locals are laid out in reverse order: the last one in order of declaration is laid out at a lower address.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 13:28

























answered Nov 14 '18 at 15:56









Margaret BloomMargaret Bloom

22.4k43067




22.4k43067












  • According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

    – Peter Cordes
    Nov 14 '18 at 16:02











  • @PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

    – Margaret Bloom
    Nov 14 '18 at 16:25











  • That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

    – Peter Cordes
    Nov 14 '18 at 16:28












  • @PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

    – Margaret Bloom
    Nov 15 '18 at 13:45

















  • According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

    – Peter Cordes
    Nov 14 '18 at 16:02











  • @PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

    – Margaret Bloom
    Nov 14 '18 at 16:25











  • That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

    – Peter Cordes
    Nov 14 '18 at 16:28












  • @PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

    – Margaret Bloom
    Nov 15 '18 at 13:45
















According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

– Peter Cordes
Nov 14 '18 at 16:02





According to a comment, the OP is using a non-standard ABI with 64-bit long in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you use long long because 64-bit integers are still only aligned by 4 bytes, not naturally aligned.

– Peter Cordes
Nov 14 '18 at 16:02













@PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

– Margaret Bloom
Nov 14 '18 at 16:25





@PeterCordes IIRC, arguments are not usually aligned on 32-bit x86, only padded to be a multiple of four bytes. Though, I may remember wrong. Yes, using a 64-bit long will shift the other argument by 4. I hope the OP will do the math themselves.

– Margaret Bloom
Nov 14 '18 at 16:25













That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

– Peter Cordes
Nov 14 '18 at 16:28






That's because alignof(long long) is only 4. Same as for struct packing. Giving long long natural alignment is only an optimization that's done whenever possible (outside of structs and arg-passing). If you passed an 8-byte or 16-byte aligned type, there would have to be padding. (And IIRC, i386 System V mentions this for __m128 args that don't fit in registers). I don't know what Windows calling conventions do about passing types that guarantee more than 4 byte alignment.

– Peter Cordes
Nov 14 '18 at 16:28














@PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

– Margaret Bloom
Nov 15 '18 at 13:45





@PeterCordes You are right: the i386 ABI mandates alignments for the arguments (and for the end of parameter block as a whole). I didn't know that. long long is aligned on 4 bytes. Microsoft, instead, is too vague in its page on x86-32 calling conventions. Their compiler doesn't seem to align long long on 8B when passed as a parameter and larger types are passed as pointers.

– Margaret Bloom
Nov 15 '18 at 13:45



















draft saved

draft discarded
















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid


  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53291230%2fdraw-the-stack-frame-and-determin-addresses-of-locals-assuming-x86-calling-conve%23new-answer', 'question_page');

);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Use pre created SQLite database for Android project in kotlin

Darth Vader #20

Ondo