Draw the stack frame and determin addresses of locals assuming x86 calling convention
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)
Two questions:
- Is it good?
- In this convention stack is with increasing addresses and heap with decreasing?
assembly x86
|
show 10 more comments
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)
Two questions:
- Is it good?
- In this convention stack is with increasing addresses and heap with decreasing?
assembly x86
You seem to have allocated 6 bytes fors
and 4 fora
. Also what's the striped slot aftera
?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 showsb
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 uselong 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
|
show 10 more comments
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)
Two questions:
- Is it good?
- In this convention stack is with increasing addresses and heap with decreasing?
assembly x86
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)
Two questions:
- Is it good?
- In this convention stack is with increasing addresses and heap with decreasing?
assembly x86
assembly x86
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 fors
and 4 fora
. Also what's the striped slot aftera
?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 showsb
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 uselong 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
|
show 10 more comments
You seem to have allocated 6 bytes fors
and 4 fora
. Also what's the striped slot aftera
?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 showsb
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 uselong 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
|
show 10 more comments
1 Answer
1
active
oldest
votes
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
orcdecl
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.
According to a comment, the OP is using a non-standard ABI with 64-bitlong
in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you uselong 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-bitlong
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 becausealignof(long long)
is only 4. Same as for struct packing. Givinglong 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 alignlong long
on 8B when passed as a parameter and larger types are passed as pointers.
– Margaret Bloom
Nov 15 '18 at 13:45
add a comment |
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
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
orcdecl
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.
According to a comment, the OP is using a non-standard ABI with 64-bitlong
in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you uselong 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-bitlong
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 becausealignof(long long)
is only 4. Same as for struct packing. Givinglong 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 alignlong long
on 8B when passed as a parameter and larger types are passed as pointers.
– Margaret Bloom
Nov 15 '18 at 13:45
add a comment |
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
orcdecl
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.
According to a comment, the OP is using a non-standard ABI with 64-bitlong
in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you uselong 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-bitlong
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 becausealignof(long long)
is only 4. Same as for struct packing. Givinglong 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 alignlong long
on 8B when passed as a parameter and larger types are passed as pointers.
– Margaret Bloom
Nov 15 '18 at 13:45
add a comment |
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
orcdecl
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.
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
orcdecl
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.
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-bitlong
in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you uselong 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-bitlong
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 becausealignof(long long)
is only 4. Same as for struct packing. Givinglong 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 alignlong long
on 8B when passed as a parameter and larger types are passed as pointers.
– Margaret Bloom
Nov 15 '18 at 13:45
add a comment |
According to a comment, the OP is using a non-standard ABI with 64-bitlong
in 32-bit mode. As I commented, you get args at +8, +12, and +20 if you uselong 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-bitlong
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 becausealignof(long long)
is only 4. Same as for struct packing. Givinglong 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 alignlong 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
add a comment |
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.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
You seem to have allocated 6 bytes for
s
and 4 fora
. Also what's the striped slot aftera
?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 uselong 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